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:
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user