| OLD | NEW |
| 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 '../parser/error_kind.dart' show ErrorKind; | 7 import '../parser/error_kind.dart' show ErrorKind; |
| 8 | 8 |
| 9 import '../scanner/error_token.dart' show ErrorToken; | 9 import '../scanner/error_token.dart' show ErrorToken; |
| 10 | 10 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 /// analyzer does. This seems like it will complicate parsing and other | 47 /// analyzer does. This seems like it will complicate parsing and other |
| 48 /// operations. | 48 /// operations. |
| 49 class ToAnalyzerTokenStreamConverter { | 49 class ToAnalyzerTokenStreamConverter { |
| 50 /// Synthetic token pointing to the first token in the analyzer token stream. | 50 /// Synthetic token pointing to the first token in the analyzer token stream. |
| 51 analyzer.Token _analyzerTokenHead; | 51 analyzer.Token _analyzerTokenHead; |
| 52 | 52 |
| 53 /// The most recently generated analyzer token, or [_analyzerTokenHead] if no | 53 /// The most recently generated analyzer token, or [_analyzerTokenHead] if no |
| 54 /// tokens have been generated yet. | 54 /// tokens have been generated yet. |
| 55 analyzer.Token _analyzerTokenTail; | 55 analyzer.Token _analyzerTokenTail; |
| 56 | 56 |
| 57 /// If a sequence of consecutive comment tokens is being processed, the first | |
| 58 /// translated analyzer comment token. Otherwise `null`. | |
| 59 analyzer.CommentToken _currentCommentHead; | |
| 60 | |
| 61 /// If a sequence of consecutive comment tokens is being processed, the last | |
| 62 /// translated analyzer comment token. Otherwise `null`. | |
| 63 analyzer.CommentToken _currentCommentTail; | |
| 64 | |
| 65 /// Stack of analyzer "begin" tokens which need to be linked up to | 57 /// Stack of analyzer "begin" tokens which need to be linked up to |
| 66 /// corresponding "end" tokens once those tokens are translated. | 58 /// corresponding "end" tokens once those tokens are translated. |
| 67 /// | 59 /// |
| 68 /// The first element of this list is always a sentinel `null` value so that | 60 /// 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. | 61 /// we don't have to check if it is empty. |
| 70 /// | 62 /// |
| 71 /// See additional documentation in [_matchGroups]. | 63 /// See additional documentation in [_matchGroups]. |
| 72 List<analyzer.BeginToken> _beginTokenStack; | 64 List<analyzer.BeginToken> _beginTokenStack; |
| 73 | 65 |
| 74 /// Stack of fasta "end" tokens corresponding to the tokens in | 66 /// Stack of fasta "end" tokens corresponding to the tokens in |
| 75 /// [_endTokenStack]. | 67 /// [_endTokenStack]. |
| 76 /// | 68 /// |
| 77 /// The first element of this list is always a sentinel `null` value so that | 69 /// The first element of this list is always a sentinel `null` value so that |
| 78 /// we don't have to check if it is empty. | 70 /// we don't have to check if it is empty. |
| 79 /// | 71 /// |
| 80 /// See additional documentation in [_matchGroups]. | 72 /// See additional documentation in [_matchGroups]. |
| 81 List<Token> _endTokenStack; | 73 List<Token> _endTokenStack; |
| 82 | 74 |
| 83 /// Converts a stream of Fasta tokens (starting with [token] and continuing to | 75 /// Converts a stream of Fasta tokens (starting with [token] and continuing to |
| 84 /// EOF) to a stream of analyzer tokens. | 76 /// EOF) to a stream of analyzer tokens. |
| 85 analyzer.Token convertTokens(Token token) { | 77 analyzer.Token convertTokens(Token token) { |
| 86 _analyzerTokenHead = new analyzer.Token(TokenType.EOF, -1); | 78 _analyzerTokenHead = new analyzer.Token(TokenType.EOF, -1); |
| 87 _analyzerTokenHead.previous = _analyzerTokenHead; | 79 _analyzerTokenHead.previous = _analyzerTokenHead; |
| 88 _analyzerTokenTail = _analyzerTokenHead; | 80 _analyzerTokenTail = _analyzerTokenHead; |
| 89 _currentCommentHead = null; | |
| 90 _currentCommentTail = null; | |
| 91 _beginTokenStack = [null]; | 81 _beginTokenStack = [null]; |
| 92 _endTokenStack = <Token>[null]; | 82 _endTokenStack = <Token>[null]; |
| 93 | 83 |
| 94 while (true) { | 84 while (true) { |
| 95 if (token.info.kind == BAD_INPUT_TOKEN) { | 85 if (token.info.kind == BAD_INPUT_TOKEN) { |
| 96 ErrorToken errorToken = token; | 86 ErrorToken errorToken = token; |
| 97 _translateErrorToken(errorToken); | 87 _translateErrorToken(errorToken); |
| 98 } else if (token.info.kind == COMMENT_TOKEN) { | |
| 99 var translatedToken = translateCommentToken(token); | |
| 100 if (_currentCommentHead == null) { | |
| 101 _currentCommentHead = _currentCommentTail = translatedToken; | |
| 102 } else { | |
| 103 _currentCommentTail.setNext(translatedToken); | |
| 104 _currentCommentTail = translatedToken; | |
| 105 } | |
| 106 } else { | 88 } else { |
| 107 var translatedToken = translateToken(token, _currentCommentHead); | 89 var translatedToken = translateToken( |
| 90 token, translateCommentTokens(token.precedingComments)); |
| 108 _matchGroups(token, translatedToken); | 91 _matchGroups(token, translatedToken); |
| 109 translatedToken.setNext(translatedToken); | 92 translatedToken.setNext(translatedToken); |
| 110 _currentCommentHead = _currentCommentTail = null; | |
| 111 _analyzerTokenTail.setNext(translatedToken); | 93 _analyzerTokenTail.setNext(translatedToken); |
| 112 translatedToken.previous = _analyzerTokenTail; | 94 translatedToken.previous = _analyzerTokenTail; |
| 113 _analyzerTokenTail = translatedToken; | 95 _analyzerTokenTail = translatedToken; |
| 114 } | 96 } |
| 115 if (token.isEof) { | 97 if (token.isEof) { |
| 116 return _analyzerTokenHead.next; | 98 return _analyzerTokenHead.next; |
| 117 } | 99 } |
| 118 token = token.next; | 100 token = token.next; |
| 119 } | 101 } |
| 120 } | 102 } |
| 121 | 103 |
| 122 /// Handles an error found during [convertTokens]. | 104 /// Handles an error found during [convertTokens]. |
| 123 /// | 105 /// |
| 124 /// Intended to be overridden by derived classes; by default, does nothing. | 106 /// Intended to be overridden by derived classes; by default, does nothing. |
| 125 void reportError(analyzer.ScannerErrorCode errorCode, int offset, | 107 void reportError(analyzer.ScannerErrorCode errorCode, int offset, |
| 126 List<Object> arguments) {} | 108 List<Object> arguments) {} |
| 127 | 109 |
| 128 /// Translates a single fasta comment token to the corresponding analyzer | 110 /// Translates a sequence of fasta comment tokens to the corresponding |
| 129 /// token. | 111 /// analyzer tokens. |
| 130 analyzer.CommentToken translateCommentToken(Token token) { | 112 analyzer.CommentToken translateCommentTokens(Token token) { |
| 131 // TODO(paulberry,ahe): It would be nice if the scanner gave us an | 113 analyzer.CommentToken translateOneComment(Token token) { |
| 132 // easier way to distinguish between the two types of comment. | 114 // TODO(paulberry,ahe): It would be nice if the scanner gave us an |
| 133 var type = token.value.startsWith('/*') | 115 // easier way to distinguish between the two types of comment. |
| 134 ? TokenType.MULTI_LINE_COMMENT | 116 var type = token.value.startsWith('/*') |
| 135 : TokenType.SINGLE_LINE_COMMENT; | 117 ? TokenType.MULTI_LINE_COMMENT |
| 136 return new analyzer.CommentToken(type, token.value, token.charOffset); | 118 : TokenType.SINGLE_LINE_COMMENT; |
| 119 return new analyzer.CommentToken(type, token.value, token.charOffset); |
| 120 } |
| 121 |
| 122 analyzer.CommentToken head; |
| 123 if (token != null) { |
| 124 head = translateOneComment(token); |
| 125 analyzer.CommentToken tail = head; |
| 126 token = token.next; |
| 127 while (token != null) { |
| 128 tail = tail.setNext(translateOneComment(token)); |
| 129 token = token.next; |
| 130 } |
| 131 } |
| 132 return head; |
| 137 } | 133 } |
| 138 | 134 |
| 139 /// Translates a single fasta non-comment token to the corresponding analyzer | 135 /// Translates a single fasta non-comment token to the corresponding analyzer |
| 140 /// token. | 136 /// token. |
| 141 /// | 137 /// |
| 142 /// [precedingComments] is not `null`, the translated token is pointed to it. | 138 /// [precedingComments] is not `null`, the translated token is pointed to it. |
| 143 analyzer.Token translateToken( | 139 analyzer.Token translateToken( |
| 144 Token token, analyzer.CommentToken precedingComments) => | 140 Token token, analyzer.CommentToken precedingComments) => |
| 145 toAnalyzerToken(token, precedingComments); | 141 toAnalyzerToken(token, precedingComments); |
| 146 | 142 |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 // tokens as appropriate. | 266 // tokens as appropriate. |
| 271 if (translatedToken is BeginGroupToken && | 267 if (translatedToken is BeginGroupToken && |
| 272 analyzerToken is analyzer.BeginToken && | 268 analyzerToken is analyzer.BeginToken && |
| 273 analyzerToken.endToken != null) { | 269 analyzerToken.endToken != null) { |
| 274 angleBracketStack.clear(); | 270 angleBracketStack.clear(); |
| 275 beginTokenStack.add(translatedToken); | 271 beginTokenStack.add(translatedToken); |
| 276 endTokenStack.add(analyzerToken.endToken); | 272 endTokenStack.add(analyzerToken.endToken); |
| 277 } | 273 } |
| 278 } | 274 } |
| 279 | 275 |
| 276 Token translateComments(analyzer.Token token) { |
| 277 if (token == null) { |
| 278 return null; |
| 279 } |
| 280 Token head = fromAnalyzerToken(token); |
| 281 Token tail = head; |
| 282 token = token.next; |
| 283 while (token != null) { |
| 284 tail.next = fromAnalyzerToken(token); |
| 285 tail = tail.next; |
| 286 token = token.next; |
| 287 } |
| 288 return head; |
| 289 } |
| 290 |
| 280 analyzer.Token translateAndAppend(analyzer.Token analyzerToken) { | 291 analyzer.Token translateAndAppend(analyzer.Token analyzerToken) { |
| 281 var token = fromAnalyzerToken(analyzerToken); | 292 var token = fromAnalyzerToken(analyzerToken); |
| 293 token.precedingComments = |
| 294 translateComments(analyzerToken.precedingComments); |
| 282 tokenTail.next = token; | 295 tokenTail.next = token; |
| 283 tokenTail = token; | 296 tokenTail = token; |
| 284 matchGroups(analyzerToken, token); | 297 matchGroups(analyzerToken, token); |
| 285 return analyzerToken.next; | 298 return analyzerToken.next; |
| 286 } | 299 } |
| 287 | 300 |
| 288 while (true) { | 301 while (true) { |
| 289 analyzer.Token commentToken = analyzerToken.precedingComments; | |
| 290 while (commentToken != null) { | |
| 291 commentToken = translateAndAppend(commentToken); | |
| 292 } | |
| 293 // TODO(paulberry): join up begingroup/endgroup. | 302 // TODO(paulberry): join up begingroup/endgroup. |
| 294 if (analyzerToken.type == TokenType.EOF) { | 303 if (analyzerToken.type == TokenType.EOF) { |
| 295 tokenTail.next = new SymbolToken(EOF_INFO, analyzerToken.offset); | 304 tokenTail.next = new SymbolToken(EOF_INFO, analyzerToken.offset); |
| 305 tokenTail.next.precedingComments = |
| 306 translateComments(analyzerToken.precedingComments); |
| 296 return tokenHead.next; | 307 return tokenHead.next; |
| 297 } | 308 } |
| 298 analyzerToken = translateAndAppend(analyzerToken); | 309 analyzerToken = translateAndAppend(analyzerToken); |
| 299 } | 310 } |
| 300 } | 311 } |
| 301 | 312 |
| 302 /// Converts a single analyzer token into a Fasta token. | 313 /// Converts a single analyzer token into a Fasta token. |
| 303 Token fromAnalyzerToken(analyzer.Token token) { | 314 Token fromAnalyzerToken(analyzer.Token token) { |
| 304 Token beginGroup(PrecedenceInfo info) => | 315 Token beginGroup(PrecedenceInfo info) => |
| 305 new BeginGroupToken(info, token.offset); | 316 new BeginGroupToken(info, token.offset); |
| (...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 764 case PERIOD_PERIOD_PERIOD_TOKEN: | 775 case PERIOD_PERIOD_PERIOD_TOKEN: |
| 765 return TokenType.PERIOD_PERIOD_PERIOD; | 776 return TokenType.PERIOD_PERIOD_PERIOD; |
| 766 // case GENERIC_METHOD_TYPE_LIST_TOKEN: | 777 // case GENERIC_METHOD_TYPE_LIST_TOKEN: |
| 767 // return TokenType.GENERIC_METHOD_TYPE_LIST; | 778 // return TokenType.GENERIC_METHOD_TYPE_LIST; |
| 768 // case GENERIC_METHOD_TYPE_ASSIGN_TOKEN: | 779 // case GENERIC_METHOD_TYPE_ASSIGN_TOKEN: |
| 769 // return TokenType.GENERIC_METHOD_TYPE_ASSIGN; | 780 // return TokenType.GENERIC_METHOD_TYPE_ASSIGN; |
| 770 default: | 781 default: |
| 771 return internalError("Unhandled token ${token.info}"); | 782 return internalError("Unhandled token ${token.info}"); |
| 772 } | 783 } |
| 773 } | 784 } |
| OLD | NEW |