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

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

Issue 2686363002: Move token stream translation logic into Fasta. (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
« no previous file with comments | « no previous file | pkg/front_end/test/scanner_fasta_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
8 ErrorKind;
9
10 import 'package:front_end/src/fasta/scanner/error_token.dart' show
11 ErrorToken;
12
7 import 'package:front_end/src/fasta/scanner/token.dart' show 13 import 'package:front_end/src/fasta/scanner/token.dart' show
8 KeywordToken, 14 KeywordToken,
9 Token; 15 Token;
10 16
11 import 'package:front_end/src/fasta/scanner/token_constants.dart'; 17 import 'package:front_end/src/fasta/scanner/token_constants.dart';
12 18
13 import 'package:front_end/src/scanner/token.dart' as analyzer show 19 import 'package:front_end/src/scanner/token.dart' as analyzer show
14 CommentToken, 20 CommentToken,
15 Keyword, 21 Keyword,
16 KeywordToken, 22 KeywordToken,
17 KeywordTokenWithComment, 23 KeywordTokenWithComment,
18 StringToken, 24 StringToken,
19 StringTokenWithComment, 25 StringTokenWithComment,
20 Token, 26 Token,
21 TokenWithComment; 27 TokenWithComment;
22 28
29 import 'package:front_end/src/scanner/errors.dart' as analyzer show
30 ScannerErrorCode;
31
23 import 'package:analyzer/dart/ast/token.dart' show 32 import 'package:analyzer/dart/ast/token.dart' show
24 TokenType; 33 TokenType;
25 34
26 import '../errors.dart' show 35 import '../errors.dart' show
27 internalError; 36 internalError;
28 37
38 /// Converts a stream of Fasta tokens (starting with [token] and continuing to
39 /// EOF) to a stream of analyzer tokens.
40 ///
41 /// If any error tokens are found in the stream, they are reported using the
42 /// [reportError] callback.
43 analyzer.Token toAnalyzerTokenStream(
44 Token token,
45 void reportError(analyzer.ScannerErrorCode errorCode, int offset,
46 List<Object> arguments)) {
47 var analyzerTokenHead = new analyzer.Token(null, 0);
48 analyzerTokenHead.previous = analyzerTokenHead;
49 var analyzerTokenTail = analyzerTokenHead;
50 // TODO(paulberry,ahe): Fasta includes comments directly in the token
51 // stream, rather than pointing to them via a "precedingComment" pointer, as
52 // analyzer does. This seems like it will complicate parsing and other
53 // operations.
ahe 2017/02/10 21:56:25 Absolutely, we should do something like precedingC
54 analyzer.CommentToken currentCommentHead;
55 analyzer.CommentToken currentCommentTail;
56 while (true) {
57 if (token.info.kind == BAD_INPUT_TOKEN) {
58 ErrorToken errorToken = token;
59 _translateErrorToken(errorToken, reportError);
60 } else if (token.info.kind == COMMENT_TOKEN) {
61 // TODO(paulberry,ahe): It would be nice if the scanner gave us an
62 // easier way to distinguish between the two types of comment.
63 var type = token.value.startsWith('/*')
64 ? TokenType.MULTI_LINE_COMMENT
65 : TokenType.SINGLE_LINE_COMMENT;
66 var translatedToken =
67 new analyzer.CommentToken(type, token.value, token.charOffset);
68 if (currentCommentHead == null) {
69 currentCommentHead = currentCommentTail = translatedToken;
70 } else {
71 currentCommentTail.setNext(translatedToken);
72 currentCommentTail = translatedToken;
73 }
74 } else {
75 var translatedToken = toAnalyzerToken(token, currentCommentHead);
76 translatedToken.setNext(translatedToken);
77 currentCommentHead = currentCommentTail = null;
78 analyzerTokenTail.setNext(translatedToken);
79 translatedToken.previous = analyzerTokenTail;
80 analyzerTokenTail = translatedToken;
81 }
82 if (token.isEof) {
83 return analyzerTokenHead.next;
84 }
85 token = token.next;
86 }
87 }
88
89 /// Determines whether the given [charOffset], which came from the non-EOF token
90 /// [token], represents the end of the input.
91 bool _isAtEnd(Token token, int charOffset) {
92 while (true) {
93 // Skip to the next token.
94 token = token.next;
95 // If we've found an EOF token, its charOffset indicates where the end of
96 // the input is.
97 if (token.isEof) return token.charOffset == charOffset;
98 // If we've found a non-error token, then we know there is additional input
99 // text after [charOffset].
100 if (token.info.kind != BAD_INPUT_TOKEN) return false;
101 // Otherwise keep looking.
102 }
103 }
104
105 /// Translates the given error [token] into an analyzer error and reports it
106 /// using [reportError].
107 void _translateErrorToken(
108 ErrorToken token,
109 void reportError(analyzer.ScannerErrorCode errorCode, int offset,
110 List<Object> arguments)) {
111 int charOffset = token.charOffset;
112 // TODO(paulberry,ahe): why is endOffset sometimes null?
113 int endOffset = token.endOffset ?? charOffset;
ahe 2017/02/10 21:56:25 That sounds bad. Would you mind filing a bug if yo
Paul Berry 2017/02/10 22:55:01 Filed https://github.com/dart-lang/sdk/issues/2874
114 void _makeError(analyzer.ScannerErrorCode errorCode, List<Object> arguments) {
115 if (_isAtEnd(token, charOffset)) {
116 // Analyzer never generates an error message past the end of the input,
117 // since such an error would not be visible in an editor.
118 // TODO(paulberry,ahe): would it make sense to replicate this behavior
119 // in fasta, or move it elsewhere in analyzer?
120 charOffset--;
121 }
122 reportError(errorCode, charOffset, arguments);
123 }
124
125 var errorCode = token.errorCode;
126 switch (errorCode) {
127 case ErrorKind.UnterminatedString:
128 // TODO(paulberry,ahe): Fasta reports the error location as the entire
129 // string; analyzer expects the end of the string.
130 charOffset = endOffset;
131 return _makeError(
132 analyzer.ScannerErrorCode.UNTERMINATED_STRING_LITERAL, null);
133 case ErrorKind.UnmatchedToken:
134 return null;
135 case ErrorKind.UnterminatedComment:
136 // TODO(paulberry,ahe): Fasta reports the error location as the entire
137 // comment; analyzer expects the end of the comment.
138 charOffset = endOffset;
139 return _makeError(
140 analyzer.ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT, null);
141 case ErrorKind.MissingExponent:
142 // TODO(paulberry,ahe): Fasta reports the error location as the entire
143 // number; analyzer expects the end of the number.
144 charOffset = endOffset;
145 return _makeError(analyzer.ScannerErrorCode.MISSING_DIGIT, null);
146 case ErrorKind.ExpectedHexDigit:
147 // TODO(paulberry,ahe): Fasta reports the error location as the entire
148 // number; analyzer expects the end of the number.
149 charOffset = endOffset;
150 return _makeError(analyzer.ScannerErrorCode.MISSING_HEX_DIGIT, null);
151 case ErrorKind.NonAsciiIdentifier:
152 case ErrorKind.NonAsciiWhitespace:
153 return _makeError(
154 analyzer.ScannerErrorCode.ILLEGAL_CHARACTER, [token.character]);
155 case ErrorKind.UnexpectedDollarInString:
156 return null;
157 default:
158 throw new UnimplementedError('$errorCode');
159 }
160 }
161
29 analyzer.Token toAnalyzerToken(Token token, 162 analyzer.Token toAnalyzerToken(Token token,
30 [analyzer.CommentToken commentToken]) { 163 [analyzer.CommentToken commentToken]) {
31 if (token == null) return null; 164 if (token == null) return null;
32 analyzer.Token makeStringToken(TokenType tokenType) { 165 analyzer.Token makeStringToken(TokenType tokenType) {
33 if (commentToken == null) { 166 if (commentToken == null) {
34 return new analyzer.StringToken(tokenType, token.value, token.charOffset); 167 return new analyzer.StringToken(tokenType, token.value, token.charOffset);
35 } else { 168 } else {
36 return new analyzer.StringTokenWithComment( 169 return new analyzer.StringTokenWithComment(
37 tokenType, token.value, token.charOffset, commentToken); 170 tokenType, token.value, token.charOffset, commentToken);
38 } 171 }
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 case BACKSLASH_TOKEN: return TokenType.BACKSLASH; 357 case BACKSLASH_TOKEN: return TokenType.BACKSLASH;
225 case PERIOD_PERIOD_PERIOD_TOKEN: return TokenType.PERIOD_PERIOD_PERIOD; 358 case PERIOD_PERIOD_PERIOD_TOKEN: return TokenType.PERIOD_PERIOD_PERIOD;
226 // case GENERIC_METHOD_TYPE_LIST_TOKEN: 359 // case GENERIC_METHOD_TYPE_LIST_TOKEN:
227 // return TokenType.GENERIC_METHOD_TYPE_LIST; 360 // return TokenType.GENERIC_METHOD_TYPE_LIST;
228 // case GENERIC_METHOD_TYPE_ASSIGN_TOKEN: 361 // case GENERIC_METHOD_TYPE_ASSIGN_TOKEN:
229 // return TokenType.GENERIC_METHOD_TYPE_ASSIGN; 362 // return TokenType.GENERIC_METHOD_TYPE_ASSIGN;
230 default: 363 default:
231 return internalError("Unhandled token ${token.info}"); 364 return internalError("Unhandled token ${token.info}");
232 } 365 }
233 } 366 }
OLDNEW
« no previous file with comments | « no previous file | pkg/front_end/test/scanner_fasta_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698