fix(syntax/lexer): stop strings at a backslash-escaped newline

The escape arm consumed whatever byte followed the backslash, so a
backslash at the end of a line swallowed the newline and the lexer ran
into the following lines until the next quote, restructuring the rest
of the document into one string token. The newline guard now applies
inside escapes too.
This commit is contained in:
2026-07-03 07:00:40 +02:00
parent 07c89a8ac9
commit ca43a3cbef
+15
View File
@@ -103,6 +103,12 @@ impl<'a> Lexer<'a> {
}
b'\\' => {
self.pos += 1;
if self.bytes.get(self.pos) == Some(&b'\n') {
// An escaped newline is not a JSON continuation,
// so the newline still terminates the line.
self.error(start, "unterminated string");
break;
}
if self.pos < self.bytes.len() {
self.advance_char();
}
@@ -259,6 +265,15 @@ mod tests {
assert_eq!(errors.len(), 1);
}
#[test]
fn backslash_before_newline_ends_the_string() {
let (tokens, errors) = tokenize("\"C:\\\ntrue");
assert_eq!(tokens[0].kind, SyntaxKind::Str);
assert_eq!(tokens[0].text, "\"C:\\");
assert_eq!(errors.len(), 1);
assert_eq!(tokens.last().unwrap().kind, SyntaxKind::True);
}
#[test]
fn invalid_number_reports_error() {
let (_, errors) = tokenize("1.2.3");