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

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

Issue 2902813005: remove fasta <--> analyzer token translation (Closed)
Patch Set: Created 3 years, 6 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/scanner/error_token.dart' show ErrorToken; 7 import 'package:front_end/src/scanner/token.dart' show Token;
8 8
9 import 'package:front_end/src/scanner/token.dart' show Keyword, Token; 9 import 'package:front_end/src/fasta/scanner/token.dart' show SymbolToken;
10
11 import 'package:front_end/src/fasta/scanner/token.dart'
12 show BeginGroupToken, CommentToken, DartDocToken, StringToken, SymbolToken;
13 10
14 import 'package:front_end/src/fasta/scanner/token_constants.dart'; 11 import 'package:front_end/src/fasta/scanner/token_constants.dart';
15 12
16 import 'package:front_end/src/scanner/errors.dart' show translateErrorToken; 13 import 'package:front_end/src/scanner/errors.dart' show translateErrorToken;
17 14
18 import 'package:front_end/src/scanner/token.dart' as analyzer
19 show
20 BeginToken,
21 BeginTokenWithComment,
22 CommentToken,
23 Keyword,
24 KeywordToken,
25 KeywordTokenWithComment,
26 StringToken,
27 StringTokenWithComment,
28 Token,
29 TokenWithComment;
30
31 import 'package:front_end/src/scanner/errors.dart' as analyzer 15 import 'package:front_end/src/scanner/errors.dart' as analyzer
32 show ScannerErrorCode; 16 show ScannerErrorCode;
33 17
34 import 'package:analyzer/dart/ast/token.dart' show TokenType;
35
36 import 'package:front_end/src/fasta/errors.dart' show internalError;
37
38 /// Class capable of converting a stream of Fasta tokens to a stream of analyzer 18 /// Class capable of converting a stream of Fasta tokens to a stream of analyzer
39 /// tokens. 19 /// tokens.
40 /// 20 ///
41 /// This is a class rather than an ordinary method so that it can be subclassed 21 /// This is a class rather than an ordinary method so that it can be subclassed
42 /// in tests. 22 /// in tests.
43 ///
44 /// TODO(paulberry,ahe): Fasta includes comments directly in the token
45 /// stream, rather than pointing to them via a "precedingComment" pointer, as
46 /// analyzer does. This seems like it will complicate parsing and other
47 /// operations.
48 class ToAnalyzerTokenStreamConverter { 23 class ToAnalyzerTokenStreamConverter {
49 /// Synthetic token pointing to the first token in the analyzer token stream.
50 analyzer.Token _analyzerTokenHead;
51
52 /// The most recently generated analyzer token, or [_analyzerTokenHead] if no
53 /// tokens have been generated yet.
54 analyzer.Token _analyzerTokenTail;
55
56 /// Stack of analyzer "begin" tokens which need to be linked up to
57 /// corresponding "end" tokens once those tokens are translated.
58 ///
59 /// The first element of this list is always a sentinel `null` value so that
60 /// we don't have to check if it is empty.
61 ///
62 /// See additional documentation in [_matchGroups].
63 List<analyzer.BeginToken> _beginTokenStack;
64
65 /// Stack of fasta "end" tokens corresponding to the tokens in
66 /// [_endTokenStack].
67 ///
68 /// The first element of this list is always a sentinel `null` value so that
69 /// we don't have to check if it is empty.
70 ///
71 /// See additional documentation in [_matchGroups].
72 List<Token> _endTokenStack;
73
74 /// Converts a stream of Fasta tokens (starting with [token] and continuing to 24 /// Converts a stream of Fasta tokens (starting with [token] and continuing to
75 /// EOF) to a stream of analyzer tokens. 25 /// EOF) to a stream of analyzer tokens. This modifies the fasta token stream
76 analyzer.Token convertTokens(Token token) { 26 /// to be an analyzer token stream by removing error tokens and reporting
77 _analyzerTokenHead = new analyzer.Token(TokenType.EOF, -1); 27 /// those errors to the associated error listener.
78 _analyzerTokenHead.previous = _analyzerTokenHead; 28 Token convertTokens(Token firstToken) {
79 _analyzerTokenTail = _analyzerTokenHead; 29 Token previous = new SymbolToken.eof(-1);
80 _beginTokenStack = [null]; 30 Token token = firstToken;
81 _endTokenStack = <Token>[null]; 31 token.previous = previous;
82 32 previous.next = token;
83 while (true) { 33 while (!token.isEof) {
84 if (token.type.kind == BAD_INPUT_TOKEN) { 34 if (token.type.kind == BAD_INPUT_TOKEN) {
85 ErrorToken errorToken = token; 35 translateErrorToken(token, reportError);
86 translateErrorToken(errorToken, reportError); 36 previous.next = token.next;
37 token.next.previous = previous;
87 } else { 38 } else {
88 var translatedToken = translateToken( 39 previous = token;
89 token, translateCommentTokens(token.precedingComments));
90 _matchGroups(token, translatedToken);
91 translatedToken.setNext(translatedToken);
92 _analyzerTokenTail.setNext(translatedToken);
93 translatedToken.previous = _analyzerTokenTail;
94 _analyzerTokenTail = translatedToken;
95 }
96 if (token.isEof) {
97 return _analyzerTokenHead.next;
98 } 40 }
99 token = token.next; 41 token = token.next;
100 } 42 }
43 return firstToken;
101 } 44 }
102 45
103 /// Handles an error found during [convertTokens]. 46 /// Handles an error found during [convertTokens].
104 /// 47 ///
105 /// Intended to be overridden by derived classes; by default, does nothing. 48 /// Intended to be overridden by derived classes; by default, does nothing.
106 void reportError(analyzer.ScannerErrorCode errorCode, int offset, 49 void reportError(analyzer.ScannerErrorCode errorCode, int offset,
107 List<Object> arguments) {} 50 List<Object> arguments) {}
108
109 /// Translates a sequence of fasta comment tokens to the corresponding
110 /// analyzer tokens.
111 analyzer.CommentToken translateCommentTokens(analyzer.Token token) {
112 analyzer.CommentToken head;
113 if (token != null) {
114 head = toAnalyzerCommentToken(token);
115 analyzer.CommentToken tail = head;
116 token = token.next;
117 while (token != null) {
118 tail = tail.setNext(toAnalyzerCommentToken(token));
119 token = token.next;
120 }
121 }
122 return head;
123 }
124
125 /// Translates a single fasta non-comment token to the corresponding analyzer
126 /// token.
127 ///
128 /// [precedingComments] is not `null`, the translated token is pointed to it.
129 analyzer.Token translateToken(
130 Token token, analyzer.CommentToken precedingComments) =>
131 toAnalyzerToken(token, precedingComments);
132
133 /// Creates appropriate begin/end token links based on the fact that [token]
134 /// was translated to [translatedToken].
135 ///
136 /// Background: both fasta and analyzer have links from a "BeginToken" to its
137 /// matching "EndToken" in a group (like parentheses and braces). However,
138 /// fasta may contain synthetic tokens from error recovery that are not mapped
139 /// to the analyzer token stream. We use [_beginTokenStack] and
140 /// [_endTokenStack] to create the appropriate links for non-synthetic tokens
141 /// in the way analyzer expects.
142 void _matchGroups(Token token, analyzer.Token translatedToken) {
143 if (identical(_endTokenStack.last, token)) {
144 _beginTokenStack.last.endToken = translatedToken;
145 _beginTokenStack.removeLast();
146 _endTokenStack.removeLast();
147 }
148 // Synthetic end tokens have a length of zero.
149 if (translatedToken is analyzer.BeginToken &&
150 token is BeginGroupToken &&
151 token.endGroup != null &&
152 token.endGroup.charOffset != token.charOffset) {
153 _beginTokenStack.add(translatedToken);
154 _endTokenStack.add(token.endGroup);
155 }
156 }
157 } 51 }
158
159 /// Converts a single Fasta comment token to an analyzer comment token.
160 analyzer.CommentToken toAnalyzerCommentToken(Token token) {
161 TokenType type;
162 if (token.type == TokenType.GENERIC_METHOD_TYPE_ASSIGN) {
163 type = TokenType.GENERIC_METHOD_TYPE_ASSIGN;
164 } else if (token.type == TokenType.GENERIC_METHOD_TYPE_LIST) {
165 type = TokenType.GENERIC_METHOD_TYPE_LIST;
166 } else {
167 // TODO(paulberry,ahe): It would be nice if the scanner gave us an
168 // easier way to distinguish between the two types of comment.
169 type = token.lexeme.startsWith('/*')
170 ? TokenType.MULTI_LINE_COMMENT
171 : TokenType.SINGLE_LINE_COMMENT;
172 }
173 return new analyzer.CommentToken(type, token.lexeme, token.charOffset);
174 }
175
176 /// Converts a stream of Analyzer tokens (starting with [token] and continuing
177 /// to EOF) to a stream of Fasta tokens.
178 ///
179 /// TODO(paulberry): Analyzer tokens do not record error conditions, so a round
180 /// trip through this function and [toAnalyzerTokenStream] will lose error
181 /// information.
182 Token fromAnalyzerTokenStream(analyzer.Token analyzerToken) {
183 Token tokenHead = new SymbolToken.eof(-1);
184 Token tokenTail = tokenHead;
185
186 // Both fasta and analyzer have links from a "BeginToken" to its matching
187 // "EndToken" in a group (like parentheses and braces). However, only fasta
188 // makes these links for angle brackets. We use these stacks to map the
189 // links from the analyzer token stream into equivalent links in the fasta
190 // token stream, and to create the links that fasta expects for angle
191 // brackets.
192
193 // Note: beginTokenStack and endTokenStack are seeded with a sentinel value
194 // so that we don't have to check if they're empty.
195 var beginTokenStack = <BeginGroupToken>[null];
196 var endTokenStack = <analyzer.Token>[null];
197 var angleBracketStack = <BeginGroupToken>[];
198 void matchGroups(analyzer.Token analyzerToken, Token translatedToken) {
199 if (identical(endTokenStack.last, analyzerToken)) {
200 angleBracketStack.clear();
201 beginTokenStack.last.endGroup = translatedToken;
202 beginTokenStack.removeLast();
203 endTokenStack.removeLast();
204 } else if (translatedToken.type.kind == LT_TOKEN) {
205 BeginGroupToken beginGroupToken = translatedToken;
206 angleBracketStack.add(beginGroupToken);
207 } else if (translatedToken.type.kind == GT_TOKEN &&
208 angleBracketStack.isNotEmpty) {
209 angleBracketStack.removeLast().endGroup = translatedToken;
210 } else if (translatedToken.type.kind == GT_GT_TOKEN &&
211 angleBracketStack.isNotEmpty) {
212 angleBracketStack.removeLast();
213 if (angleBracketStack.isNotEmpty) {
214 angleBracketStack.removeLast().endGroup = translatedToken;
215 }
216 }
217 // TODO(paulberry): generate synthetic closer tokens and "UnmatchedToken"
218 // tokens as appropriate.
219 if (translatedToken is BeginGroupToken &&
220 analyzerToken is analyzer.BeginToken &&
221 analyzerToken.endToken != null) {
222 angleBracketStack.clear();
223 beginTokenStack.add(translatedToken);
224 endTokenStack.add(analyzerToken.endToken);
225 }
226 }
227
228 analyzer.Token translateAndAppend(analyzer.Token analyzerToken) {
229 var token = fromAnalyzerToken(analyzerToken);
230 // Sanity check
231 if (analyzerToken.precedingComments != null) {
232 if (token.precedingComments == null) {
233 return internalError(
234 'expected translated token $token to have preceedingComments');
235 }
236 } else {
237 if (token.precedingComments != null) {
238 return internalError('token $token has unexpected preceedingComments');
239 }
240 }
241 tokenTail.next = token;
242 tokenTail.next.previous = tokenTail; // ignore: deprecated_member_use
243 tokenTail = token;
244 matchGroups(analyzerToken, token);
245 return analyzerToken.next;
246 }
247
248 while (true) {
249 // TODO(paulberry): join up begingroup/endgroup.
250 if (analyzerToken.type == TokenType.EOF) {
251 SymbolToken eof = new SymbolToken.eof(analyzerToken.offset);
252 tokenTail.next = eof;
253 eof.previous = tokenTail; // ignore: deprecated_member_use
254 eof.precedingComments =
255 _translateComments(analyzerToken.precedingComments);
256 eof.next = eof;
257 return tokenHead.next;
258 }
259 analyzerToken = translateAndAppend(analyzerToken);
260 }
261 }
262
263 /// Converts a single analyzer token into a Fasta token.
264 Token fromAnalyzerToken(analyzer.Token token) {
265 Token comments = _translateComments(token.precedingComments);
266 Token beginGroup(TokenType type) =>
267 new BeginGroupToken(type, token.offset, comments);
268 Token string(TokenType type) =>
269 new StringToken.fromString(type, token.lexeme, token.offset,
270 precedingComments: comments);
271 Token symbol(TokenType type) => new SymbolToken(type, token.offset, comments);
272 if (token.type.isKeyword) {
273 var keyword = Keyword.keywords[token.lexeme];
274 if (keyword != null) {
275 return new analyzer.KeywordTokenWithComment(
276 keyword, token.offset, comments);
277 } else {
278 return internalError("Unrecognized keyword: '${token.lexeme}'.");
279 }
280 }
281 switch (token.type) {
282 case TokenType.DOUBLE:
283 return string(TokenType.DOUBLE);
284 case TokenType.HEXADECIMAL:
285 return string(TokenType.HEXADECIMAL);
286 case TokenType.IDENTIFIER:
287 // Certain identifiers have special grammatical meanings even though they
288 // are neither keywords nor built-in identifiers (e.g. "async"). Analyzer
289 // represents these as identifiers. Fasta represents them as keywords
290 // with the "isPseudo" property.
291 var keyword = Keyword.keywords[token.lexeme];
292 if (keyword != null) {
293 assert(keyword.isPseudo);
294 return new analyzer.KeywordTokenWithComment(
295 keyword, token.offset, comments);
296 } else {
297 return string(TokenType.IDENTIFIER);
298 }
299 break;
300 case TokenType.INT:
301 return string(TokenType.INT);
302 case TokenType.MULTI_LINE_COMMENT:
303 if (token.lexeme.startsWith('/**')) {
304 return new DartDocToken.fromSubstring(TokenType.MULTI_LINE_COMMENT,
305 token.lexeme, 0, token.lexeme.length, 0);
306 }
307 return new CommentToken.fromSubstring(TokenType.MULTI_LINE_COMMENT,
308 token.lexeme, 0, token.lexeme.length, 0);
309 case TokenType.SCRIPT_TAG:
310 return string(TokenType.SCRIPT_TAG);
311 case TokenType.SINGLE_LINE_COMMENT:
312 if (token.lexeme.startsWith('///')) {
313 return new DartDocToken.fromSubstring(TokenType.SINGLE_LINE_COMMENT,
314 token.lexeme, 0, token.lexeme.length, 0);
315 }
316 return new CommentToken.fromSubstring(TokenType.SINGLE_LINE_COMMENT,
317 token.lexeme, 0, token.lexeme.length, 0);
318 case TokenType.STRING:
319 return string(TokenType.STRING);
320 case TokenType.AMPERSAND:
321 return symbol(TokenType.AMPERSAND);
322 case TokenType.AMPERSAND_AMPERSAND:
323 return symbol(TokenType.AMPERSAND_AMPERSAND);
324 case TokenType.AMPERSAND_AMPERSAND_EQ:
325 return symbol(TokenType.AMPERSAND_AMPERSAND_EQ);
326 case TokenType.AMPERSAND_EQ:
327 return symbol(TokenType.AMPERSAND_EQ);
328 case TokenType.AT:
329 return symbol(TokenType.AT);
330 case TokenType.BANG:
331 return symbol(TokenType.BANG);
332 case TokenType.BANG_EQ:
333 return symbol(TokenType.BANG_EQ);
334 case TokenType.BAR:
335 return symbol(TokenType.BAR);
336 case TokenType.BAR_BAR:
337 return symbol(TokenType.BAR_BAR);
338 case TokenType.BAR_BAR_EQ:
339 return symbol(TokenType.BAR_BAR_EQ);
340 case TokenType.BAR_EQ:
341 return symbol(TokenType.BAR_EQ);
342 case TokenType.COLON:
343 return symbol(TokenType.COLON);
344 case TokenType.COMMA:
345 return symbol(TokenType.COMMA);
346 case TokenType.CARET:
347 return symbol(TokenType.CARET);
348 case TokenType.CARET_EQ:
349 return symbol(TokenType.CARET_EQ);
350 case TokenType.CLOSE_CURLY_BRACKET:
351 return symbol(TokenType.CLOSE_CURLY_BRACKET);
352 case TokenType.CLOSE_PAREN:
353 return symbol(TokenType.CLOSE_PAREN);
354 case TokenType.CLOSE_SQUARE_BRACKET:
355 return symbol(TokenType.CLOSE_SQUARE_BRACKET);
356 case TokenType.EQ:
357 return symbol(TokenType.EQ);
358 case TokenType.EQ_EQ:
359 return symbol(TokenType.EQ_EQ);
360 case TokenType.FUNCTION:
361 return symbol(TokenType.FUNCTION);
362 case TokenType.GT:
363 return symbol(TokenType.GT);
364 case TokenType.GT_EQ:
365 return symbol(TokenType.GT_EQ);
366 case TokenType.GT_GT:
367 return symbol(TokenType.GT_GT);
368 case TokenType.GT_GT_EQ:
369 return symbol(TokenType.GT_GT_EQ);
370 case TokenType.HASH:
371 return symbol(TokenType.HASH);
372 case TokenType.INDEX:
373 return symbol(TokenType.INDEX);
374 case TokenType.INDEX_EQ:
375 return symbol(TokenType.INDEX_EQ);
376 case TokenType.LT:
377 return beginGroup(TokenType.LT);
378 case TokenType.LT_EQ:
379 return symbol(TokenType.LT_EQ);
380 case TokenType.LT_LT:
381 return symbol(TokenType.LT_LT);
382 case TokenType.LT_LT_EQ:
383 return symbol(TokenType.LT_LT_EQ);
384 case TokenType.MINUS:
385 return symbol(TokenType.MINUS);
386 case TokenType.MINUS_EQ:
387 return symbol(TokenType.MINUS_EQ);
388 case TokenType.MINUS_MINUS:
389 return symbol(TokenType.MINUS_MINUS);
390 case TokenType.OPEN_CURLY_BRACKET:
391 return beginGroup(TokenType.OPEN_CURLY_BRACKET);
392 case TokenType.OPEN_PAREN:
393 return beginGroup(TokenType.OPEN_PAREN);
394 case TokenType.OPEN_SQUARE_BRACKET:
395 return beginGroup(TokenType.OPEN_SQUARE_BRACKET);
396 case TokenType.PERCENT:
397 return symbol(TokenType.PERCENT);
398 case TokenType.PERCENT_EQ:
399 return symbol(TokenType.PERCENT_EQ);
400 case TokenType.PERIOD:
401 return symbol(TokenType.PERIOD);
402 case TokenType.PERIOD_PERIOD:
403 return symbol(TokenType.PERIOD_PERIOD);
404 case TokenType.PLUS:
405 return symbol(TokenType.PLUS);
406 case TokenType.PLUS_EQ:
407 return symbol(TokenType.PLUS_EQ);
408 case TokenType.PLUS_PLUS:
409 return symbol(TokenType.PLUS_PLUS);
410 case TokenType.QUESTION:
411 return symbol(TokenType.QUESTION);
412 case TokenType.QUESTION_PERIOD:
413 return symbol(TokenType.QUESTION_PERIOD);
414 case TokenType.QUESTION_QUESTION:
415 return symbol(TokenType.QUESTION_QUESTION);
416 case TokenType.QUESTION_QUESTION_EQ:
417 return symbol(TokenType.QUESTION_QUESTION_EQ);
418 case TokenType.SEMICOLON:
419 return symbol(TokenType.SEMICOLON);
420 case TokenType.SLASH:
421 return symbol(TokenType.SLASH);
422 case TokenType.SLASH_EQ:
423 return symbol(TokenType.SLASH_EQ);
424 case TokenType.STAR:
425 return symbol(TokenType.STAR);
426 case TokenType.STAR_EQ:
427 return symbol(TokenType.STAR_EQ);
428 case TokenType.STRING_INTERPOLATION_EXPRESSION:
429 return beginGroup(TokenType.STRING_INTERPOLATION_EXPRESSION);
430 case TokenType.STRING_INTERPOLATION_IDENTIFIER:
431 return symbol(TokenType.STRING_INTERPOLATION_IDENTIFIER);
432 case TokenType.TILDE:
433 return symbol(TokenType.TILDE);
434 case TokenType.TILDE_SLASH:
435 return symbol(TokenType.TILDE_SLASH);
436 case TokenType.TILDE_SLASH_EQ:
437 return symbol(TokenType.TILDE_SLASH_EQ);
438 case TokenType.BACKPING:
439 return symbol(TokenType.BACKPING);
440 case TokenType.BACKSLASH:
441 return symbol(TokenType.BACKSLASH);
442 case TokenType.PERIOD_PERIOD_PERIOD:
443 return symbol(TokenType.PERIOD_PERIOD_PERIOD);
444 case TokenType.GENERIC_METHOD_TYPE_ASSIGN:
445 return new CommentToken.fromSubstring(
446 TokenType.GENERIC_METHOD_TYPE_ASSIGN,
447 token.lexeme,
448 0,
449 token.lexeme.length,
450 0);
451 case TokenType.GENERIC_METHOD_TYPE_LIST:
452 return new CommentToken.fromSubstring(TokenType.GENERIC_METHOD_TYPE_LIST,
453 token.lexeme, 0, token.lexeme.length, 0);
454 default:
455 return internalError('Unhandled token type ${token.type}');
456 }
457 }
458
459 analyzer.Token toAnalyzerToken(Token token,
460 [analyzer.CommentToken commentToken]) {
461 if (token == null) return null;
462 analyzer.Token makeStringToken(TokenType tokenType) {
463 if (commentToken == null) {
464 return new analyzer.StringToken(
465 tokenType, token.lexeme, token.charOffset);
466 } else {
467 return new analyzer.StringTokenWithComment(
468 tokenType, token.lexeme, token.charOffset, commentToken);
469 }
470 }
471
472 analyzer.Token makeBeginToken(TokenType tokenType) {
473 if (commentToken == null) {
474 return new analyzer.BeginToken(tokenType, token.charOffset);
475 } else {
476 return new analyzer.BeginTokenWithComment(
477 tokenType, token.charOffset, commentToken);
478 }
479 }
480
481 switch (token.kind) {
482 case DOUBLE_TOKEN:
483 return makeStringToken(TokenType.DOUBLE);
484
485 case HEXADECIMAL_TOKEN:
486 return makeStringToken(TokenType.HEXADECIMAL);
487
488 case IDENTIFIER_TOKEN:
489 return makeStringToken(TokenType.IDENTIFIER);
490
491 case INT_TOKEN:
492 return makeStringToken(TokenType.INT);
493
494 case KEYWORD_TOKEN:
495 var syntax = token.type.lexeme;
496 // TODO(paulberry): if the map lookup proves to be too slow, consider
497 // using a switch statement, or perhaps a string of
498 // "if (identical(syntax, "foo"))" checks. (Note that identical checks
499 // should be safe because the Fasta scanner uses string literals for
500 // the values of keyword.syntax.)
501 var keyword =
502 _keywordMap[syntax] ?? internalError('Unknown keyword: $syntax');
503 if (commentToken == null) {
504 return new analyzer.KeywordToken(keyword, token.charOffset);
505 } else {
506 return new analyzer.KeywordTokenWithComment(
507 keyword, token.charOffset, commentToken);
508 }
509 break;
510
511 case SCRIPT_TOKEN:
512 return makeStringToken(TokenType.SCRIPT_TAG);
513
514 case STRING_TOKEN:
515 return makeStringToken(TokenType.STRING);
516
517 case OPEN_CURLY_BRACKET_TOKEN:
518 case OPEN_SQUARE_BRACKET_TOKEN:
519 case OPEN_PAREN_TOKEN:
520 case STRING_INTERPOLATION_TOKEN:
521 return makeBeginToken(token.type);
522
523 default:
524 if (commentToken == null) {
525 return new analyzer.Token(token.type, token.charOffset);
526 } else {
527 return new analyzer.TokenWithComment(
528 token.type, token.charOffset, commentToken);
529 }
530 break;
531 }
532 }
533
534 analyzer.Token _translateComments(analyzer.Token token) {
535 if (token == null) {
536 return null;
537 }
538 Token head = fromAnalyzerToken(token);
539 Token tail = head;
540 token = token.next;
541 while (token != null) {
542 tail.next = fromAnalyzerToken(token);
543 tail.next.previous = tail; // ignore: deprecated_member_use
544 tail = tail.next;
545 token = token.next;
546 }
547 return head;
548 }
549
550 final _keywordMap = {
551 "assert": analyzer.Keyword.ASSERT,
552 "break": analyzer.Keyword.BREAK,
553 "case": analyzer.Keyword.CASE,
554 "catch": analyzer.Keyword.CATCH,
555 "class": analyzer.Keyword.CLASS,
556 "const": analyzer.Keyword.CONST,
557 "continue": analyzer.Keyword.CONTINUE,
558 "default": analyzer.Keyword.DEFAULT,
559 "do": analyzer.Keyword.DO,
560 "else": analyzer.Keyword.ELSE,
561 "enum": analyzer.Keyword.ENUM,
562 "extends": analyzer.Keyword.EXTENDS,
563 "false": analyzer.Keyword.FALSE,
564 "final": analyzer.Keyword.FINAL,
565 "finally": analyzer.Keyword.FINALLY,
566 "for": analyzer.Keyword.FOR,
567 "if": analyzer.Keyword.IF,
568 "in": analyzer.Keyword.IN,
569 "new": analyzer.Keyword.NEW,
570 "null": analyzer.Keyword.NULL,
571 "rethrow": analyzer.Keyword.RETHROW,
572 "return": analyzer.Keyword.RETURN,
573 "super": analyzer.Keyword.SUPER,
574 "switch": analyzer.Keyword.SWITCH,
575 "this": analyzer.Keyword.THIS,
576 "throw": analyzer.Keyword.THROW,
577 "true": analyzer.Keyword.TRUE,
578 "try": analyzer.Keyword.TRY,
579 "var": analyzer.Keyword.VAR,
580 "void": analyzer.Keyword.VOID,
581 "while": analyzer.Keyword.WHILE,
582 "with": analyzer.Keyword.WITH,
583 //
584 "is": analyzer.Keyword.IS,
585 //
586 "abstract": analyzer.Keyword.ABSTRACT,
587 "as": analyzer.Keyword.AS,
588 "covariant": analyzer.Keyword.COVARIANT,
589 "deferred": analyzer.Keyword.DEFERRED,
590 "dynamic": analyzer.Keyword.DYNAMIC,
591 "export": analyzer.Keyword.EXPORT,
592 "external": analyzer.Keyword.EXTERNAL,
593 "factory": analyzer.Keyword.FACTORY,
594 "get": analyzer.Keyword.GET,
595 "implements": analyzer.Keyword.IMPLEMENTS,
596 "import": analyzer.Keyword.IMPORT,
597 "library": analyzer.Keyword.LIBRARY,
598 "operator": analyzer.Keyword.OPERATOR,
599 "part": analyzer.Keyword.PART,
600 "set": analyzer.Keyword.SET,
601 "static": analyzer.Keyword.STATIC,
602 "typedef": analyzer.Keyword.TYPEDEF,
603 //
604 "async": analyzer.Keyword.ASYNC,
605 "await": analyzer.Keyword.AWAIT,
606 "Function": analyzer.Keyword.FUNCTION,
607 "hide": analyzer.Keyword.HIDE,
608 "native": analyzer.Keyword.NATIVE,
609 "of": analyzer.Keyword.OF,
610 "on": analyzer.Keyword.ON,
611 "patch": analyzer.Keyword.PATCH,
612 "show": analyzer.Keyword.SHOW,
613 "source": analyzer.Keyword.SOURCE,
614 "sync": analyzer.Keyword.SYNC,
615 "yield": analyzer.Keyword.YIELD,
616 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698