| Index: pkg/front_end/lib/src/scanner/errors.dart
|
| diff --git a/pkg/front_end/lib/src/scanner/errors.dart b/pkg/front_end/lib/src/scanner/errors.dart
|
| index bcf0c56585f52f7fcf62353e86605a15427dc998..10853c1f946b76d91b6a0654d8442b082c4438a9 100644
|
| --- a/pkg/front_end/lib/src/scanner/errors.dart
|
| +++ b/pkg/front_end/lib/src/scanner/errors.dart
|
| @@ -3,6 +3,9 @@
|
| // BSD-style license that can be found in the LICENSE file.
|
|
|
| import 'package:front_end/src/base/errors.dart';
|
| +import 'package:front_end/src/fasta/scanner/error_token.dart';
|
| +import 'package:front_end/src/fasta/scanner/token.dart';
|
| +import 'package:front_end/src/fasta/scanner/token_constants.dart';
|
|
|
| /**
|
| * The error codes used for errors detected by the scanner.
|
| @@ -57,3 +60,78 @@ class ScannerErrorCode extends ErrorCode {
|
| @override
|
| ErrorType get type => ErrorType.SYNTACTIC_ERROR;
|
| }
|
| +
|
| +/**
|
| + * Used to report a scan error at the given offset.
|
| + * The [errorCode] is the error code indicating the nature of the error.
|
| + * The [arguments] are any arguments needed to complete the error message
|
| + */
|
| +typedef ReportError(
|
| + ScannerErrorCode errorCode, int offset, List<Object> arguments);
|
| +
|
| +/// Translates the given error [token] into an analyzer error and reports it
|
| +/// using [reportError].
|
| +void translateErrorToken(ErrorToken token, ReportError reportError) {
|
| + int charOffset = token.charOffset;
|
| + // TODO(paulberry,ahe): why is endOffset sometimes null?
|
| + int endOffset = token.endOffset ?? charOffset;
|
| + void _makeError(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(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(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(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(ScannerErrorCode.MISSING_HEX_DIGIT, null);
|
| + case ErrorKind.NonAsciiIdentifier:
|
| + case ErrorKind.NonAsciiWhitespace:
|
| + return _makeError(ScannerErrorCode.ILLEGAL_CHARACTER, [token.character]);
|
| + case ErrorKind.UnexpectedDollarInString:
|
| + return null;
|
| + default:
|
| + throw new UnimplementedError('$errorCode');
|
| + }
|
| +}
|
| +
|
| +/// 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.
|
| + }
|
| +}
|
|
|