OLD | NEW |
---|---|
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 /** | 5 library front_end.src.scanner.token; |
Brian Wilkerson
2016/11/08 20:53:24
Not sure why we dropped the doc comment.
Paul Berry
2016/11/08 21:47:06
Re-added.
| |
6 * Defines the tokens that are produced by the scanner, used by the parser, and | |
7 * referenced from the [AST structure](ast.dart). | |
8 */ | |
9 library analyzer.dart.ast.token; | |
10 | 6 |
11 import 'dart:collection'; | 7 import 'dart:collection'; |
12 | 8 |
13 import 'package:analyzer/dart/ast/syntactic_entity.dart'; | 9 import 'package:front_end/src/scanner/string_utilities.dart'; |
14 import 'package:analyzer/src/dart/ast/token.dart' show SimpleToken, TokenClass; | 10 import 'package:front_end/src/scanner/syntactic_entity.dart'; |
11 | |
12 /** | |
13 * The opening half of a grouping pair of tokens. This is used for curly | |
14 * brackets ('{'), parentheses ('('), and square brackets ('['). | |
15 */ | |
16 class BeginToken extends SimpleToken { | |
Brian Wilkerson
2016/11/08 20:53:24
As discussed off-line, I liked the previous separa
Paul Berry
2016/11/08 21:47:06
Acknowledged.
| |
17 /** | |
18 * The token that corresponds to this token. | |
19 */ | |
20 Token endToken; | |
21 | |
22 /** | |
23 * Initialize a newly created token to have the given [type] at the given | |
24 * [offset]. | |
25 */ | |
26 BeginToken(TokenType type, int offset) : super(type, offset) { | |
27 assert(type == TokenType.OPEN_CURLY_BRACKET || | |
28 type == TokenType.OPEN_PAREN || | |
29 type == TokenType.OPEN_SQUARE_BRACKET || | |
30 type == TokenType.STRING_INTERPOLATION_EXPRESSION); | |
31 } | |
32 | |
33 @override | |
34 Token copy() => new BeginToken(type, offset); | |
35 } | |
36 | |
37 /** | |
38 * A begin token that is preceded by comments. | |
39 */ | |
40 class BeginTokenWithComment extends BeginToken implements TokenWithComment { | |
41 /** | |
42 * The first comment in the list of comments that precede this token. | |
43 */ | |
44 @override | |
45 CommentToken _precedingComment; | |
46 | |
47 /** | |
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 | |
50 * [_precedingComment]. | |
51 */ | |
52 BeginTokenWithComment(TokenType type, int offset, this._precedingComment) | |
53 : super(type, offset) { | |
54 _setCommentParent(_precedingComment); | |
55 } | |
56 | |
57 @override | |
58 CommentToken get precedingComments => _precedingComment; | |
59 | |
60 @override | |
61 void set precedingComments(CommentToken comment) { | |
62 _precedingComment = comment; | |
63 _setCommentParent(_precedingComment); | |
64 } | |
65 | |
66 @override | |
67 void applyDelta(int delta) { | |
68 super.applyDelta(delta); | |
69 Token token = precedingComments; | |
70 while (token != null) { | |
71 token.applyDelta(delta); | |
72 token = token.next; | |
73 } | |
74 } | |
75 | |
76 @override | |
77 Token copy() => | |
78 new BeginTokenWithComment(type, offset, copyComments(precedingComments)); | |
79 } | |
80 | |
81 /** | |
82 * A token representing a comment. | |
83 */ | |
84 class CommentToken extends StringToken { | |
85 /** | |
86 * The token that contains this comment. | |
87 */ | |
88 TokenWithComment parent; | |
89 | |
90 /** | |
91 * Initialize a newly created token to represent a token of the given [type] | |
92 * with the given [value] at the given [offset]. | |
93 */ | |
94 CommentToken(TokenType type, String value, int offset) | |
95 : super(type, value, offset); | |
96 | |
97 @override | |
98 CommentToken copy() => new CommentToken(type, _value, offset); | |
99 | |
100 /** | |
101 * Remove this comment token from the list. | |
102 * | |
103 * This is used when we decide to interpret the comment as syntax. | |
104 */ | |
105 void remove() { | |
106 if (previous != null) { | |
107 previous.setNextWithoutSettingPrevious(next); | |
108 next?.previous = previous; | |
109 } else { | |
110 assert(parent.precedingComments == this); | |
111 parent.precedingComments = next; | |
112 } | |
113 } | |
114 } | |
115 | |
116 /** | |
117 * A documentation comment token. | |
118 */ | |
119 class DocumentationCommentToken extends CommentToken { | |
120 /** | |
121 * The references embedded within the documentation comment. | |
122 * This list will be empty unless this is a documentation comment that has | |
123 * references embedded within it. | |
124 */ | |
125 final List<Token> references = <Token>[]; | |
126 | |
127 /** | |
128 * Initialize a newly created token to represent a token of the given [type] | |
129 * with the given [value] at the given [offset]. | |
130 */ | |
131 DocumentationCommentToken(TokenType type, String value, int offset) | |
132 : super(type, value, offset); | |
133 | |
134 @override | |
135 CommentToken copy() { | |
136 DocumentationCommentToken copy = | |
137 new DocumentationCommentToken(type, _value, offset); | |
138 references.forEach((ref) => copy.references.add(ref.copy())); | |
139 return copy; | |
140 } | |
141 } | |
15 | 142 |
16 /** | 143 /** |
17 * The keywords in the Dart programming language. | 144 * The keywords in the Dart programming language. |
18 * | 145 * |
19 * Clients may not extend, implement or mix-in this class. | 146 * Clients may not extend, implement or mix-in this class. |
20 */ | 147 */ |
21 class Keyword { | 148 class Keyword { |
22 static const Keyword ABSTRACT = const Keyword._('ABSTRACT', "abstract", true); | 149 static const Keyword ABSTRACT = const Keyword._('ABSTRACT', "abstract", true); |
23 | 150 |
24 static const Keyword AS = const Keyword._('AS', "as", true); | 151 static const Keyword AS = const Keyword._('AS', "as", true); |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
208 LinkedHashMap<String, Keyword> result = | 335 LinkedHashMap<String, Keyword> result = |
209 new LinkedHashMap<String, Keyword>(); | 336 new LinkedHashMap<String, Keyword>(); |
210 for (Keyword keyword in values) { | 337 for (Keyword keyword in values) { |
211 result[keyword.syntax] = keyword; | 338 result[keyword.syntax] = keyword; |
212 } | 339 } |
213 return result; | 340 return result; |
214 } | 341 } |
215 } | 342 } |
216 | 343 |
217 /** | 344 /** |
345 * A token representing a keyword in the language. | |
346 */ | |
347 class KeywordToken extends SimpleToken { | |
348 @override | |
349 final Keyword keyword; | |
350 | |
351 /** | |
352 * Initialize a newly created token to represent the given [keyword] at the | |
353 * given [offset]. | |
354 */ | |
355 KeywordToken(this.keyword, int offset) : super(TokenType.KEYWORD, offset); | |
356 | |
357 @override | |
358 String get lexeme => keyword.syntax; | |
359 | |
360 @override | |
361 Token copy() => new KeywordToken(keyword, offset); | |
362 | |
363 @override | |
364 Keyword value() => keyword; | |
365 } | |
366 | |
367 /** | |
368 * A keyword token that is preceded by comments. | |
369 */ | |
370 class KeywordTokenWithComment extends KeywordToken implements TokenWithComment { | |
371 /** | |
372 * The first comment in the list of comments that precede this token. | |
373 */ | |
374 @override | |
375 CommentToken _precedingComment; | |
376 | |
377 /** | |
378 * Initialize a newly created token to to represent the given [keyword] at the | |
379 * given [offset] and to be preceded by the comments reachable from the given | |
380 * [_precedingComment]. | |
381 */ | |
382 KeywordTokenWithComment(Keyword keyword, int offset, this._precedingComment) | |
383 : super(keyword, offset) { | |
384 _setCommentParent(_precedingComment); | |
385 } | |
386 | |
387 @override | |
388 CommentToken get precedingComments => _precedingComment; | |
389 | |
390 void set precedingComments(CommentToken comment) { | |
391 _precedingComment = comment; | |
392 _setCommentParent(_precedingComment); | |
393 } | |
394 | |
395 @override | |
396 void applyDelta(int delta) { | |
397 super.applyDelta(delta); | |
398 Token token = precedingComments; | |
399 while (token != null) { | |
400 token.applyDelta(delta); | |
401 token = token.next; | |
402 } | |
403 } | |
404 | |
405 @override | |
406 Token copy() => new KeywordTokenWithComment( | |
407 keyword, offset, copyComments(precedingComments)); | |
408 } | |
409 | |
410 /** | |
411 * A token that was scanned from the input. Each token knows which tokens | |
412 * precede and follow it, acting as a link in a doubly linked list of tokens. | |
413 */ | |
414 class SimpleToken implements Token { | |
415 /** | |
416 * The type of the token. | |
417 */ | |
418 @override | |
419 final TokenType type; | |
420 | |
421 /** | |
422 * The offset from the beginning of the file to the first character in the | |
423 * token. | |
424 */ | |
425 @override | |
426 int offset = 0; | |
427 | |
428 /** | |
429 * The previous token in the token stream. | |
430 */ | |
431 @override | |
432 Token previous; | |
433 | |
434 /** | |
435 * The next token in the token stream. | |
436 */ | |
437 Token _next; | |
438 | |
439 /** | |
440 * Initialize a newly created token to have the given [type] and [offset]. | |
441 */ | |
442 SimpleToken(this.type, this.offset); | |
443 | |
444 @override | |
445 int get end => offset + length; | |
446 | |
447 @override | |
448 bool get isOperator => type.isOperator; | |
449 | |
450 @override | |
451 bool get isSynthetic => length == 0; | |
452 | |
453 @override | |
454 bool get isUserDefinableOperator => type.isUserDefinableOperator; | |
455 | |
456 @override | |
457 Keyword get keyword => null; | |
458 | |
459 @override | |
460 int get length => lexeme.length; | |
461 | |
462 @override | |
463 String get lexeme => type.lexeme; | |
464 | |
465 @override | |
466 Token get next => _next; | |
467 | |
468 @override | |
469 CommentToken get precedingComments => null; | |
470 | |
471 @override | |
472 void applyDelta(int delta) { | |
473 offset += delta; | |
474 } | |
475 | |
476 @override | |
477 Token copy() => new Token(type, offset); | |
478 | |
479 @override | |
480 Token copyComments(Token token) { | |
481 if (token == null) { | |
482 return null; | |
483 } | |
484 Token head = token.copy(); | |
485 Token tail = head; | |
486 token = token.next; | |
487 while (token != null) { | |
488 tail = tail.setNext(token.copy()); | |
489 token = token.next; | |
490 } | |
491 return head; | |
492 } | |
493 | |
494 @override | |
495 bool matchesAny(List<TokenType> types) { | |
496 for (TokenType type in types) { | |
497 if (this.type == type) { | |
498 return true; | |
499 } | |
500 } | |
501 return false; | |
502 } | |
503 | |
504 @override | |
505 Token setNext(Token token) { | |
506 _next = token; | |
507 token.previous = this; | |
508 return token; | |
509 } | |
510 | |
511 @override | |
512 Token setNextWithoutSettingPrevious(Token token) { | |
513 _next = token; | |
514 return token; | |
515 } | |
516 | |
517 @override | |
518 String toString() => lexeme; | |
519 | |
520 @override | |
521 Object value() => type.lexeme; | |
522 | |
523 /** | |
524 * Sets the `parent` property to `this` for the given [comment] and all the | |
525 * next tokens. | |
526 */ | |
527 void _setCommentParent(CommentToken comment) { | |
528 while (comment != null) { | |
529 comment.parent = this; | |
530 comment = comment.next; | |
531 } | |
532 } | |
533 } | |
534 | |
535 /** | |
536 * A token whose value is independent of it's type. | |
537 */ | |
538 class StringToken extends SimpleToken { | |
539 /** | |
540 * The lexeme represented by this token. | |
541 */ | |
542 String _value; | |
543 | |
544 /** | |
545 * Initialize a newly created token to represent a token of the given [type] | |
546 * with the given [value] at the given [offset]. | |
547 */ | |
548 StringToken(TokenType type, String value, int offset) : super(type, offset) { | |
549 this._value = StringUtilities.intern(value); | |
550 } | |
551 | |
552 @override | |
553 String get lexeme => _value; | |
554 | |
555 @override | |
556 Token copy() => new StringToken(type, _value, offset); | |
557 | |
558 @override | |
559 String value() => _value; | |
560 } | |
561 | |
562 /** | |
563 * A string token that is preceded by comments. | |
564 */ | |
565 class StringTokenWithComment extends StringToken implements TokenWithComment { | |
566 /** | |
567 * The first comment in the list of comments that precede this token. | |
568 */ | |
569 CommentToken _precedingComment; | |
570 | |
571 /** | |
572 * Initialize a newly created token to have the given [type] at the given | |
573 * [offset] and to be preceded by the comments reachable from the given | |
574 * [comment]. | |
575 */ | |
576 StringTokenWithComment( | |
577 TokenType type, String value, int offset, this._precedingComment) | |
578 : super(type, value, offset) { | |
579 _setCommentParent(_precedingComment); | |
580 } | |
581 | |
582 @override | |
583 CommentToken get precedingComments => _precedingComment; | |
584 | |
585 void set precedingComments(CommentToken comment) { | |
586 _precedingComment = comment; | |
587 _setCommentParent(_precedingComment); | |
588 } | |
589 | |
590 @override | |
591 void applyDelta(int delta) { | |
592 super.applyDelta(delta); | |
593 Token token = precedingComments; | |
594 while (token != null) { | |
595 token.applyDelta(delta); | |
596 token = token.next; | |
597 } | |
598 } | |
599 | |
600 @override | |
601 Token copy() => new StringTokenWithComment( | |
602 type, lexeme, offset, copyComments(precedingComments)); | |
603 } | |
604 | |
605 /** | |
218 * A token that was scanned from the input. Each token knows which tokens | 606 * A token that was scanned from the input. Each token knows which tokens |
219 * precede and follow it, acting as a link in a doubly linked list of tokens. | 607 * precede and follow it, acting as a link in a doubly linked list of tokens. |
220 * | 608 * |
221 * Clients may not extend, implement or mix-in this class. | 609 * Clients may not extend, implement or mix-in this class. |
222 */ | 610 */ |
223 abstract class Token implements SyntacticEntity { | 611 abstract class Token implements SyntacticEntity { |
224 /** | 612 /** |
225 * Initialize a newly created token to have the given [type] and [offset]. | 613 * Initialize a newly created token to have the given [type] and [offset]. |
226 */ | 614 */ |
227 factory Token(TokenType type, int offset) = SimpleToken; | 615 factory Token(TokenType type, int offset) = SimpleToken; |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
359 if (token != null && (offset < 0 || token.offset < offset)) { | 747 if (token != null && (offset < 0 || token.offset < offset)) { |
360 first = token; | 748 first = token; |
361 offset = token.offset; | 749 offset = token.offset; |
362 } | 750 } |
363 } | 751 } |
364 return first; | 752 return first; |
365 } | 753 } |
366 } | 754 } |
367 | 755 |
368 /** | 756 /** |
757 * The classes (or groups) of tokens with a similar use. | |
758 */ | |
759 class TokenClass { | |
760 /** | |
761 * A value used to indicate that the token type is not part of any specific | |
762 * class of token. | |
763 */ | |
764 static const TokenClass NO_CLASS = const TokenClass('NO_CLASS'); | |
765 | |
766 /** | |
767 * A value used to indicate that the token type is an additive operator. | |
768 */ | |
769 static const TokenClass ADDITIVE_OPERATOR = | |
770 const TokenClass('ADDITIVE_OPERATOR', 13); | |
771 | |
772 /** | |
773 * A value used to indicate that the token type is an assignment operator. | |
774 */ | |
775 static const TokenClass ASSIGNMENT_OPERATOR = | |
776 const TokenClass('ASSIGNMENT_OPERATOR', 1); | |
777 | |
778 /** | |
779 * A value used to indicate that the token type is a bitwise-and operator. | |
780 */ | |
781 static const TokenClass BITWISE_AND_OPERATOR = | |
782 const TokenClass('BITWISE_AND_OPERATOR', 11); | |
783 | |
784 /** | |
785 * A value used to indicate that the token type is a bitwise-or operator. | |
786 */ | |
787 static const TokenClass BITWISE_OR_OPERATOR = | |
788 const TokenClass('BITWISE_OR_OPERATOR', 9); | |
789 | |
790 /** | |
791 * A value used to indicate that the token type is a bitwise-xor operator. | |
792 */ | |
793 static const TokenClass BITWISE_XOR_OPERATOR = | |
794 const TokenClass('BITWISE_XOR_OPERATOR', 10); | |
795 | |
796 /** | |
797 * A value used to indicate that the token type is a cascade operator. | |
798 */ | |
799 static const TokenClass CASCADE_OPERATOR = | |
800 const TokenClass('CASCADE_OPERATOR', 2); | |
801 | |
802 /** | |
803 * A value used to indicate that the token type is a conditional operator. | |
804 */ | |
805 static const TokenClass CONDITIONAL_OPERATOR = | |
806 const TokenClass('CONDITIONAL_OPERATOR', 3); | |
807 | |
808 /** | |
809 * A value used to indicate that the token type is an equality operator. | |
810 */ | |
811 static const TokenClass EQUALITY_OPERATOR = | |
812 const TokenClass('EQUALITY_OPERATOR', 7); | |
813 | |
814 /** | |
815 * A value used to indicate that the token type is an if-null operator. | |
816 */ | |
817 static const TokenClass IF_NULL_OPERATOR = | |
818 const TokenClass('IF_NULL_OPERATOR', 4); | |
819 | |
820 /** | |
821 * A value used to indicate that the token type is a logical-and operator. | |
822 */ | |
823 static const TokenClass LOGICAL_AND_OPERATOR = | |
824 const TokenClass('LOGICAL_AND_OPERATOR', 6); | |
825 | |
826 /** | |
827 * A value used to indicate that the token type is a logical-or operator. | |
828 */ | |
829 static const TokenClass LOGICAL_OR_OPERATOR = | |
830 const TokenClass('LOGICAL_OR_OPERATOR', 5); | |
831 | |
832 /** | |
833 * A value used to indicate that the token type is a multiplicative operator. | |
834 */ | |
835 static const TokenClass MULTIPLICATIVE_OPERATOR = | |
836 const TokenClass('MULTIPLICATIVE_OPERATOR', 14); | |
837 | |
838 /** | |
839 * A value used to indicate that the token type is a relational operator. | |
840 */ | |
841 static const TokenClass RELATIONAL_OPERATOR = | |
842 const TokenClass('RELATIONAL_OPERATOR', 8); | |
843 | |
844 /** | |
845 * A value used to indicate that the token type is a shift operator. | |
846 */ | |
847 static const TokenClass SHIFT_OPERATOR = | |
848 const TokenClass('SHIFT_OPERATOR', 12); | |
849 | |
850 /** | |
851 * A value used to indicate that the token type is a unary operator. | |
852 */ | |
853 static const TokenClass UNARY_POSTFIX_OPERATOR = | |
854 const TokenClass('UNARY_POSTFIX_OPERATOR', 16); | |
855 | |
856 /** | |
857 * A value used to indicate that the token type is a unary operator. | |
858 */ | |
859 static const TokenClass UNARY_PREFIX_OPERATOR = | |
860 const TokenClass('UNARY_PREFIX_OPERATOR', 15); | |
861 | |
862 /** | |
863 * The name of the token class. | |
864 */ | |
865 final String name; | |
866 | |
867 /** | |
868 * The precedence of tokens of this class, or `0` if the such tokens do not | |
869 * represent an operator. | |
870 */ | |
871 final int precedence; | |
872 | |
873 /** | |
874 * Initialize a newly created class of tokens to have the given [name] and | |
875 * [precedence]. | |
876 */ | |
877 const TokenClass(this.name, [this.precedence = 0]); | |
878 | |
879 @override | |
880 String toString() => name; | |
881 } | |
882 | |
883 /** | |
369 * The types of tokens that can be returned by the scanner. | 884 * The types of tokens that can be returned by the scanner. |
370 * | 885 * |
371 * Clients may not extend, implement or mix-in this class. | 886 * Clients may not extend, implement or mix-in this class. |
372 */ | 887 */ |
373 class TokenType { | 888 class TokenType { |
374 /** | 889 /** |
375 * The type of the token that marks the start or end of the input. | 890 * The type of the token that marks the start or end of the input. |
376 */ | 891 */ |
377 static const TokenType EOF = const _EndOfFileTokenType(); | 892 static const TokenType EOF = const _EndOfFileTokenType(); |
378 | 893 |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
723 * Return the precedence of the token, or `0` if the token does not represent | 1238 * Return the precedence of the token, or `0` if the token does not represent |
724 * an operator. | 1239 * an operator. |
725 */ | 1240 */ |
726 int get precedence => _tokenClass.precedence; | 1241 int get precedence => _tokenClass.precedence; |
727 | 1242 |
728 @override | 1243 @override |
729 String toString() => name; | 1244 String toString() => name; |
730 } | 1245 } |
731 | 1246 |
732 /** | 1247 /** |
1248 * A normal token that is preceded by comments. | |
1249 */ | |
1250 class TokenWithComment extends SimpleToken { | |
1251 /** | |
1252 * The first comment in the list of comments that precede this token. | |
1253 */ | |
1254 CommentToken _precedingComment; | |
1255 | |
1256 /** | |
1257 * Initialize a newly created token to have the given [type] at the given | |
1258 * [offset] and to be preceded by the comments reachable from the given | |
1259 * [comment]. | |
1260 */ | |
1261 TokenWithComment(TokenType type, int offset, this._precedingComment) | |
1262 : super(type, offset) { | |
1263 _setCommentParent(_precedingComment); | |
1264 } | |
1265 | |
1266 @override | |
1267 CommentToken get precedingComments => _precedingComment; | |
1268 | |
1269 void set precedingComments(CommentToken comment) { | |
1270 _precedingComment = comment; | |
1271 _setCommentParent(_precedingComment); | |
1272 } | |
1273 | |
1274 @override | |
1275 Token copy() => | |
1276 new TokenWithComment(type, offset, copyComments(precedingComments)); | |
1277 } | |
1278 | |
1279 /** | |
733 * A token representing the end (either the head or the tail) of a stream of | 1280 * A token representing the end (either the head or the tail) of a stream of |
734 * tokens. | 1281 * tokens. |
735 */ | 1282 */ |
736 class _EndOfFileTokenType extends TokenType { | 1283 class _EndOfFileTokenType extends TokenType { |
737 /** | 1284 /** |
738 * Initialize a newly created token. | 1285 * Initialize a newly created token. |
739 */ | 1286 */ |
740 const _EndOfFileTokenType() : super._('EOF', TokenClass.NO_CLASS, ''); | 1287 const _EndOfFileTokenType() : super._('EOF', TokenClass.NO_CLASS, ''); |
741 | 1288 |
742 @override | 1289 @override |
743 String toString() => '-eof-'; | 1290 String toString() => '-eof-'; |
744 } | 1291 } |
OLD | NEW |