Fix scanner if source ends with an unterminated string

This commit is contained in:
ViveNoctem
2025-11-09 19:07:01 +01:00
committed by Simon Binder
parent 25d09d3365
commit 5e4dfc8886
2 changed files with 29 additions and 8 deletions
@@ -313,7 +313,10 @@ class Scanner {
}
final value = source
.substring(_startOffset + (binary ? 2 : 1), _currentOffset - 1)
.substring(
_startOffset + (binary ? 2 : 1),
_currentOffset - (properlyClosed ? 1 : 0),
)
.replaceAll("''", "'");
tokens.add(StringLiteralToken(value, _currentSpan, binary: binary));
}
+25 -7
View File
@@ -74,14 +74,32 @@ void main() {
expect(scanner.tokens[1].type, TokenType.eof);
});
test('issues error for unterminated string literals', () {
final scanner = Scanner("'unterminated")..scanTokens();
group("parse unterminated string literals", () {
test('issues error', () {
final scanner = Scanner("'unterminated")..scanTokens();
expect(
scanner.errors,
contains(const TypeMatcher<TokenizerError>()
.having((e) => e.message, 'message', 'Unterminated string')),
);
expect(
scanner.errors,
contains(const TypeMatcher<TokenizerError>()
.having((e) => e.message, 'message', 'Unterminated string')),
);
expect(scanner.tokens, [
isA<StringLiteralToken>()
.having((e) => e.value, 'value', 'unterminated'),
isA<Token>().having((e) => e.type, 'type', TokenType.eof),
]);
});
test('does not crash if the input ends with apostrophe', () {
final scanner = Scanner("'")..scanTokens();
expect(
scanner.errors,
contains(const TypeMatcher<TokenizerError>()
.having((e) => e.message, 'message', 'Unterminated string')),
);
});
});
test('binary string literal', () {