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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/front_end/test/scanner_fasta_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/front_end/lib/src/fasta/analyzer/token_utils.dart
diff --git a/pkg/front_end/lib/src/fasta/analyzer/token_utils.dart b/pkg/front_end/lib/src/fasta/analyzer/token_utils.dart
index cd0fb140b86ba2dc5b5114fb1f98dd2af0d59e99..1a75623201d7e07cfd4a3f629ae5ab1e98b9f61b 100644
--- a/pkg/front_end/lib/src/fasta/analyzer/token_utils.dart
+++ b/pkg/front_end/lib/src/fasta/analyzer/token_utils.dart
@@ -4,6 +4,12 @@
library fasta.analyzer.token_utils;
+import 'package:front_end/src/fasta/parser/error_kind.dart' show
+ ErrorKind;
+
+import 'package:front_end/src/fasta/scanner/error_token.dart' show
+ ErrorToken;
+
import 'package:front_end/src/fasta/scanner/token.dart' show
KeywordToken,
Token;
@@ -20,12 +26,139 @@ import 'package:front_end/src/scanner/token.dart' as analyzer show
Token,
TokenWithComment;
+import 'package:front_end/src/scanner/errors.dart' as analyzer show
+ ScannerErrorCode;
+
import 'package:analyzer/dart/ast/token.dart' show
TokenType;
import '../errors.dart' show
internalError;
+/// Converts a stream of Fasta tokens (starting with [token] and continuing to
+/// EOF) to a stream of analyzer tokens.
+///
+/// If any error tokens are found in the stream, they are reported using the
+/// [reportError] callback.
+analyzer.Token toAnalyzerTokenStream(
+ Token token,
+ void reportError(analyzer.ScannerErrorCode errorCode, int offset,
+ List<Object> arguments)) {
+ var analyzerTokenHead = new analyzer.Token(null, 0);
+ analyzerTokenHead.previous = analyzerTokenHead;
+ var analyzerTokenTail = analyzerTokenHead;
+ // TODO(paulberry,ahe): Fasta includes comments directly in the token
+ // stream, rather than pointing to them via a "precedingComment" pointer, as
+ // analyzer does. This seems like it will complicate parsing and other
+ // operations.
ahe 2017/02/10 21:56:25 Absolutely, we should do something like precedingC
+ analyzer.CommentToken currentCommentHead;
+ analyzer.CommentToken currentCommentTail;
+ while (true) {
+ if (token.info.kind == BAD_INPUT_TOKEN) {
+ ErrorToken errorToken = token;
+ _translateErrorToken(errorToken, reportError);
+ } else if (token.info.kind == COMMENT_TOKEN) {
+ // TODO(paulberry,ahe): It would be nice if the scanner gave us an
+ // easier way to distinguish between the two types of comment.
+ var type = token.value.startsWith('/*')
+ ? TokenType.MULTI_LINE_COMMENT
+ : TokenType.SINGLE_LINE_COMMENT;
+ var translatedToken =
+ new analyzer.CommentToken(type, token.value, token.charOffset);
+ if (currentCommentHead == null) {
+ currentCommentHead = currentCommentTail = translatedToken;
+ } else {
+ currentCommentTail.setNext(translatedToken);
+ currentCommentTail = translatedToken;
+ }
+ } else {
+ var translatedToken = toAnalyzerToken(token, currentCommentHead);
+ translatedToken.setNext(translatedToken);
+ currentCommentHead = currentCommentTail = null;
+ analyzerTokenTail.setNext(translatedToken);
+ translatedToken.previous = analyzerTokenTail;
+ analyzerTokenTail = translatedToken;
+ }
+ if (token.isEof) {
+ return analyzerTokenHead.next;
+ }
+ token = token.next;
+ }
+}
+
+/// Determines whether the given [charOffset], which came from the non-EOF token
+/// [token], represents the end of the input.
+bool _isAtEnd(Token token, int charOffset) {
+ while (true) {
+ // Skip to the next token.
+ token = token.next;
+ // If we've found an EOF token, its charOffset indicates where the end of
+ // the input is.
+ if (token.isEof) return token.charOffset == charOffset;
+ // If we've found a non-error token, then we know there is additional input
+ // text after [charOffset].
+ if (token.info.kind != BAD_INPUT_TOKEN) return false;
+ // Otherwise keep looking.
+ }
+}
+
+/// Translates the given error [token] into an analyzer error and reports it
+/// using [reportError].
+void _translateErrorToken(
+ ErrorToken token,
+ void reportError(analyzer.ScannerErrorCode errorCode, int offset,
+ List<Object> arguments)) {
+ int charOffset = token.charOffset;
+ // TODO(paulberry,ahe): why is endOffset sometimes null?
+ 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
+ void _makeError(analyzer.ScannerErrorCode errorCode, List<Object> arguments) {
+ if (_isAtEnd(token, charOffset)) {
+ // Analyzer never generates an error message past the end of the input,
+ // since such an error would not be visible in an editor.
+ // TODO(paulberry,ahe): would it make sense to replicate this behavior
+ // in fasta, or move it elsewhere in analyzer?
+ charOffset--;
+ }
+ reportError(errorCode, charOffset, arguments);
+ }
+
+ var errorCode = token.errorCode;
+ switch (errorCode) {
+ case ErrorKind.UnterminatedString:
+ // TODO(paulberry,ahe): Fasta reports the error location as the entire
+ // string; analyzer expects the end of the string.
+ charOffset = endOffset;
+ return _makeError(
+ analyzer.ScannerErrorCode.UNTERMINATED_STRING_LITERAL, null);
+ case ErrorKind.UnmatchedToken:
+ return null;
+ case ErrorKind.UnterminatedComment:
+ // TODO(paulberry,ahe): Fasta reports the error location as the entire
+ // comment; analyzer expects the end of the comment.
+ charOffset = endOffset;
+ return _makeError(
+ analyzer.ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT, null);
+ case ErrorKind.MissingExponent:
+ // TODO(paulberry,ahe): Fasta reports the error location as the entire
+ // number; analyzer expects the end of the number.
+ charOffset = endOffset;
+ return _makeError(analyzer.ScannerErrorCode.MISSING_DIGIT, null);
+ case ErrorKind.ExpectedHexDigit:
+ // TODO(paulberry,ahe): Fasta reports the error location as the entire
+ // number; analyzer expects the end of the number.
+ charOffset = endOffset;
+ return _makeError(analyzer.ScannerErrorCode.MISSING_HEX_DIGIT, null);
+ case ErrorKind.NonAsciiIdentifier:
+ case ErrorKind.NonAsciiWhitespace:
+ return _makeError(
+ analyzer.ScannerErrorCode.ILLEGAL_CHARACTER, [token.character]);
+ case ErrorKind.UnexpectedDollarInString:
+ return null;
+ default:
+ throw new UnimplementedError('$errorCode');
+ }
+}
+
analyzer.Token toAnalyzerToken(Token token,
[analyzer.CommentToken commentToken]) {
if (token == null) return null;
« 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