Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(325)

Side by Side Diff: pkg/front_end/lib/src/fasta/analyzer/token_utils.dart

Issue 2690073003: When translating analyzer/fasta token streams, match up begin/end tokens. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2016, 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 library fasta.analyzer.token_utils; 5 library fasta.analyzer.token_utils;
6 6
7 import 'package:front_end/src/fasta/parser/error_kind.dart' show 7 import 'package:front_end/src/fasta/parser/error_kind.dart' show
8 ErrorKind; 8 ErrorKind;
9 9
10 import 'package:front_end/src/fasta/scanner/error_token.dart' show 10 import 'package:front_end/src/fasta/scanner/error_token.dart' show
11 ErrorToken; 11 ErrorToken,
12 UnmatchedToken;
12 13
13 import 'package:front_end/src/fasta/scanner/keyword.dart' show 14 import 'package:front_end/src/fasta/scanner/keyword.dart' show
14 Keyword; 15 Keyword;
15 16
16 import 'package:front_end/src/fasta/scanner/precedence.dart'; 17 import 'package:front_end/src/fasta/scanner/precedence.dart';
17 18
18 import 'package:front_end/src/fasta/scanner/token.dart' show 19 import 'package:front_end/src/fasta/scanner/token.dart' show
19 BeginGroupToken, 20 BeginGroupToken,
20 KeywordToken, 21 KeywordToken,
21 StringToken, 22 StringToken,
22 SymbolToken, 23 SymbolToken,
23 Token; 24 Token;
24 25
25 import 'package:front_end/src/fasta/scanner/token_constants.dart'; 26 import 'package:front_end/src/fasta/scanner/token_constants.dart';
26 27
27 import 'package:front_end/src/scanner/token.dart' as analyzer show 28 import 'package:front_end/src/scanner/token.dart' as analyzer show
29 BeginToken,
30 BeginTokenWithComment,
28 CommentToken, 31 CommentToken,
29 Keyword, 32 Keyword,
30 KeywordToken, 33 KeywordToken,
31 KeywordTokenWithComment, 34 KeywordTokenWithComment,
32 StringToken, 35 StringToken,
33 StringTokenWithComment, 36 StringTokenWithComment,
34 Token, 37 Token,
35 TokenWithComment; 38 TokenWithComment;
36 39
37 import 'package:front_end/src/scanner/errors.dart' as analyzer show 40 import 'package:front_end/src/scanner/errors.dart' as analyzer show
(...skipping 16 matching lines...) Expand all
54 List<Object> arguments)) { 57 List<Object> arguments)) {
55 var analyzerTokenHead = new analyzer.Token(null, 0); 58 var analyzerTokenHead = new analyzer.Token(null, 0);
56 analyzerTokenHead.previous = analyzerTokenHead; 59 analyzerTokenHead.previous = analyzerTokenHead;
57 var analyzerTokenTail = analyzerTokenHead; 60 var analyzerTokenTail = analyzerTokenHead;
58 // TODO(paulberry,ahe): Fasta includes comments directly in the token 61 // TODO(paulberry,ahe): Fasta includes comments directly in the token
59 // stream, rather than pointing to them via a "precedingComment" pointer, as 62 // stream, rather than pointing to them via a "precedingComment" pointer, as
60 // analyzer does. This seems like it will complicate parsing and other 63 // analyzer does. This seems like it will complicate parsing and other
61 // operations. 64 // operations.
62 analyzer.CommentToken currentCommentHead; 65 analyzer.CommentToken currentCommentHead;
63 analyzer.CommentToken currentCommentTail; 66 analyzer.CommentToken currentCommentTail;
67 // Note: beginTokenStack and endTokenStack are seeded with a sentinel value
68 // so that we don't have to check if they're empty.
69 var beginTokenStack = <analyzer.BeginToken>[null];
70 var endTokenStack = <Token>[null];
71 void matchGroups(Token token, analyzer.Token translatedToken) {
72 // If this token closes a group, set the corresponding opener token
Siggi Cherem (dart-lang) 2017/02/15 00:23:10 super optional nit - (IMO not worth making a chang
73 // to point to it.
74 if (identical(endTokenStack.last, token)) {
75 beginTokenStack.last.endToken = translatedToken;
76 beginTokenStack.removeLast();
77 endTokenStack.removeLast();
78 }
79 // If this token opens a group, and there is a matching closer that's not
Siggi Cherem (dart-lang) 2017/02/15 00:23:10 minor terminology nit here: consider using closing
80 // synthetic, put it on the stack. The easiest way to tell whether the
81 // closer is synthetic is to see if it has the same offset as the opener.
82 if (translatedToken is analyzer.BeginToken && token is BeginGroupToken &&
83 token.endGroup != null && token.endGroup.charOffset != token.charOffset) {
ahe 2017/02/14 11:28:32 Long line.
Paul Berry 2017/02/14 12:40:39 Sorry. My usual workflow is hampered by not being
84 beginTokenStack.add(translatedToken);
85 endTokenStack.add(token.endGroup);
86 }
87 }
88
64 while (true) { 89 while (true) {
65 if (token.info.kind == BAD_INPUT_TOKEN) { 90 if (token.info.kind == BAD_INPUT_TOKEN) {
66 ErrorToken errorToken = token; 91 ErrorToken errorToken = token;
67 _translateErrorToken(errorToken, reportError); 92 _translateErrorToken(errorToken, reportError);
68 } else if (token.info.kind == COMMENT_TOKEN) { 93 } else if (token.info.kind == COMMENT_TOKEN) {
69 // TODO(paulberry,ahe): It would be nice if the scanner gave us an 94 // TODO(paulberry,ahe): It would be nice if the scanner gave us an
70 // easier way to distinguish between the two types of comment. 95 // easier way to distinguish between the two types of comment.
71 var type = token.value.startsWith('/*') 96 var type = token.value.startsWith('/*')
72 ? TokenType.MULTI_LINE_COMMENT 97 ? TokenType.MULTI_LINE_COMMENT
73 : TokenType.SINGLE_LINE_COMMENT; 98 : TokenType.SINGLE_LINE_COMMENT;
74 var translatedToken = 99 var translatedToken =
75 new analyzer.CommentToken(type, token.value, token.charOffset); 100 new analyzer.CommentToken(type, token.value, token.charOffset);
76 if (currentCommentHead == null) { 101 if (currentCommentHead == null) {
77 currentCommentHead = currentCommentTail = translatedToken; 102 currentCommentHead = currentCommentTail = translatedToken;
78 } else { 103 } else {
79 currentCommentTail.setNext(translatedToken); 104 currentCommentTail.setNext(translatedToken);
80 currentCommentTail = translatedToken; 105 currentCommentTail = translatedToken;
81 } 106 }
82 } else { 107 } else {
83 var translatedToken = toAnalyzerToken(token, currentCommentHead); 108 var translatedToken = toAnalyzerToken(token, currentCommentHead);
109 matchGroups(token, translatedToken);
84 translatedToken.setNext(translatedToken); 110 translatedToken.setNext(translatedToken);
85 currentCommentHead = currentCommentTail = null; 111 currentCommentHead = currentCommentTail = null;
86 analyzerTokenTail.setNext(translatedToken); 112 analyzerTokenTail.setNext(translatedToken);
87 translatedToken.previous = analyzerTokenTail; 113 translatedToken.previous = analyzerTokenTail;
88 analyzerTokenTail = translatedToken; 114 analyzerTokenTail = translatedToken;
89 } 115 }
90 if (token.isEof) { 116 if (token.isEof) {
91 return analyzerTokenHead.next; 117 return analyzerTokenHead.next;
92 } 118 }
93 token = token.next; 119 token = token.next;
94 } 120 }
95 } 121 }
96 122
97 /// Converts a stream of Analyzer tokens (starting with [token] and continuing 123 /// Converts a stream of Analyzer tokens (starting with [token] and continuing
98 /// to EOF) to a stream of Fasta tokens. 124 /// to EOF) to a stream of Fasta tokens.
99 /// 125 ///
100 /// TODO(paulberry): Analyzer tokens do not record error conditions, so a round 126 /// TODO(paulberry): Analyzer tokens do not record error conditions, so a round
101 /// trip through this function and [toAnalyzerTokenStream] will lose error 127 /// trip through this function and [toAnalyzerTokenStream] will lose error
102 /// information. 128 /// information.
103 Token fromAnalyzerTokenStream(analyzer.Token analyzerToken) { 129 Token fromAnalyzerTokenStream(analyzer.Token analyzerToken) {
104 Token tokenHead = new SymbolToken(EOF_INFO, -1); 130 Token tokenHead = new SymbolToken(EOF_INFO, -1);
105 Token tokenTail = tokenHead; 131 Token tokenTail = tokenHead;
132 // Note: beginTokenStack and endTokenStack are seeded with a sentinel value
133 // so that we don't have to check if they're empty.
134 var beginTokenStack = <BeginGroupToken>[null];
135 var endTokenStack = <analyzer.Token>[null];
136 void matchGroups(analyzer.Token analyzerToken, Token translatedToken) {
137 // If this token closes a group, set the corresponding opener token to point
138 // to it.
139 if (identical(endTokenStack.last, analyzerToken)) {
140 beginTokenStack.last.endGroup = translatedToken;
141 beginTokenStack.removeLast();
142 endTokenStack.removeLast();
143 }
144 // If this token opens a group, and there is a matching closer, put it on
145 // the stack.
146 // TODO(paulberry): generate synthetic closer tokens and "UnmatchedToken"
147 // tokens as appropriate.
148 // TODO(paulberry): match up "<" and ">"/">>" (analyzer doesn't match
149 // these).
150 if (translatedToken is BeginGroupToken && analyzerToken is analyzer.BeginTok en &&
ahe 2017/02/14 11:28:32 Long line.
Paul Berry 2017/02/14 12:40:39 Done.
151 analyzerToken.endToken != null) {
152 beginTokenStack.add(translatedToken);
153 endTokenStack.add(analyzerToken.endToken);
154 }
155 }
106 analyzer.Token translateAndAppend(analyzer.Token analyzerToken) { 156 analyzer.Token translateAndAppend(analyzer.Token analyzerToken) {
107 var token = fromAnalyzerToken(analyzerToken); 157 var token = fromAnalyzerToken(analyzerToken);
108 tokenTail.next = token; 158 tokenTail.next = token;
109 tokenTail = token; 159 tokenTail = token;
160 matchGroups(analyzerToken, token);
110 return analyzerToken.next; 161 return analyzerToken.next;
111 } 162 }
112 163
113 while (true) { 164 while (true) {
114 analyzer.Token commentToken = analyzerToken.precedingComments; 165 analyzer.Token commentToken = analyzerToken.precedingComments;
115 while (commentToken != null) { 166 while (commentToken != null) {
116 commentToken = translateAndAppend(commentToken); 167 commentToken = translateAndAppend(commentToken);
117 } 168 }
118 // TODO(paulberry): join up begingroup/endgroup. 169 // TODO(paulberry): join up begingroup/endgroup.
119 if (analyzerToken.type == TokenType.EOF) { 170 if (analyzerToken.type == TokenType.EOF) {
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 if (token == null) return null; 424 if (token == null) return null;
374 analyzer.Token makeStringToken(TokenType tokenType) { 425 analyzer.Token makeStringToken(TokenType tokenType) {
375 if (commentToken == null) { 426 if (commentToken == null) {
376 return new analyzer.StringToken(tokenType, token.value, token.charOffset); 427 return new analyzer.StringToken(tokenType, token.value, token.charOffset);
377 } else { 428 } else {
378 return new analyzer.StringTokenWithComment( 429 return new analyzer.StringTokenWithComment(
379 tokenType, token.value, token.charOffset, commentToken); 430 tokenType, token.value, token.charOffset, commentToken);
380 } 431 }
381 } 432 }
382 433
434 analyzer.Token makeBeginToken(TokenType tokenType) {
435 if (commentToken == null) {
436 return new analyzer.BeginToken(tokenType, token.charOffset);
437 } else {
438 return new analyzer.BeginTokenWithComment(tokenType, token.charOffset, com mentToken);
ahe 2017/02/14 11:28:32 Long line.
Paul Berry 2017/02/14 12:40:39 Done.
439 }
440 }
441
383 switch (token.kind) { 442 switch (token.kind) {
384 case DOUBLE_TOKEN: 443 case DOUBLE_TOKEN:
385 return makeStringToken(TokenType.DOUBLE); 444 return makeStringToken(TokenType.DOUBLE);
386 445
387 case HEXADECIMAL_TOKEN: 446 case HEXADECIMAL_TOKEN:
388 return makeStringToken(TokenType.HEXADECIMAL); 447 return makeStringToken(TokenType.HEXADECIMAL);
389 448
390 case IDENTIFIER_TOKEN: 449 case IDENTIFIER_TOKEN:
391 return makeStringToken(TokenType.IDENTIFIER); 450 return makeStringToken(TokenType.IDENTIFIER);
392 451
(...skipping 23 matching lines...) Expand all
416 return new analyzer.KeywordToken(keyword, token.charOffset); 475 return new analyzer.KeywordToken(keyword, token.charOffset);
417 } else { 476 } else {
418 return new analyzer.KeywordTokenWithComment( 477 return new analyzer.KeywordTokenWithComment(
419 keyword, token.charOffset, commentToken); 478 keyword, token.charOffset, commentToken);
420 } 479 }
421 break; 480 break;
422 481
423 case STRING_TOKEN: 482 case STRING_TOKEN:
424 return makeStringToken(TokenType.STRING); 483 return makeStringToken(TokenType.STRING);
425 484
485 case OPEN_CURLY_BRACKET_TOKEN:
486 case OPEN_SQUARE_BRACKET_TOKEN:
487 case OPEN_PAREN_TOKEN:
488 case STRING_INTERPOLATION_TOKEN:
489 return makeBeginToken(getTokenType(token));
490
426 default: 491 default:
427 if (commentToken == null) { 492 if (commentToken == null) {
428 return new analyzer.Token(getTokenType(token), token.charOffset); 493 return new analyzer.Token(getTokenType(token), token.charOffset);
429 } else { 494 } else {
430 return new analyzer.TokenWithComment( 495 return new analyzer.TokenWithComment(
431 getTokenType(token), token.charOffset, commentToken); 496 getTokenType(token), token.charOffset, commentToken);
432 } 497 }
433 break; 498 break;
434 } 499 }
435 } 500 }
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 case BACKSLASH_TOKEN: return TokenType.BACKSLASH; 631 case BACKSLASH_TOKEN: return TokenType.BACKSLASH;
567 case PERIOD_PERIOD_PERIOD_TOKEN: return TokenType.PERIOD_PERIOD_PERIOD; 632 case PERIOD_PERIOD_PERIOD_TOKEN: return TokenType.PERIOD_PERIOD_PERIOD;
568 // case GENERIC_METHOD_TYPE_LIST_TOKEN: 633 // case GENERIC_METHOD_TYPE_LIST_TOKEN:
569 // return TokenType.GENERIC_METHOD_TYPE_LIST; 634 // return TokenType.GENERIC_METHOD_TYPE_LIST;
570 // case GENERIC_METHOD_TYPE_ASSIGN_TOKEN: 635 // case GENERIC_METHOD_TYPE_ASSIGN_TOKEN:
571 // return TokenType.GENERIC_METHOD_TYPE_ASSIGN; 636 // return TokenType.GENERIC_METHOD_TYPE_ASSIGN;
572 default: 637 default:
573 return internalError("Unhandled token ${token.info}"); 638 return internalError("Unhandled token ${token.info}");
574 } 639 }
575 } 640 }
OLDNEW
« no previous file with comments | « no previous file | pkg/front_end/test/scanner_fasta_test.dart » ('j') | pkg/front_end/test/scanner_fasta_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698