fix(lua): consume escaped short-string newlines

This commit is contained in:
taoxin 2026-08-24 10:31:56 +08:00
parent f192855ba4
commit aaad674f38
2 changed files with 32 additions and 3 deletions

View file

@ -193,4 +193,23 @@ describe('parser-loader ABI load-smoke (#1922)', () => {
expect(tree.rootNode.hasError).toBe(false);
}
});
it('accepts a real newline escaped inside a short string', () => {
let grammar: unknown;
try {
grammar = getLanguageGrammar(SupportedLanguages.Lua);
} catch (err) {
expect(err).toBeInstanceOf(Error);
return;
}
const parser = new Parser();
parser.setLanguage(grammar as Parameters<Parser['setLanguage']>[0]);
const snippet = String.raw`local value = "line\
continued"
`;
const tree = parser.parse(snippet);
expect(tree.rootNode.type).toBe('chunk');
expect(tree.rootNode.hasError).toBe(false);
});
});

View file

@ -171,10 +171,20 @@ bool tree_sitter_lua_external_scanner_scan(void *payload, TSLexer *lexer, const
// consume any character till a short string's end, new line or eof
do
{
// consume any character after a backslash, unless it's a new line or eof
if (consume_if(lexer, '\\') && (lexer->lookahead == '\n' || lexer->eof(lexer)))
// A backslash escapes the following character. Lua also permits a
// backslash followed by a real newline to continue a short string;
// consume that newline so the scanner does not remain stuck at it.
if (consume_if(lexer, '\\'))
{
break;
if (lexer->lookahead == '\n')
{
consume(lexer);
continue;
}
if (lexer->eof(lexer))
{
break;
}
}
consume(lexer);