From 3f1884ac5e3cfee1b99563ebd593687c388acf51 Mon Sep 17 00:00:00 2001 From: Matthew Saw Date: Mon, 28 Sep 2026 21:52:36 +0800 Subject: [PATCH] fix(scanner): insert semicolon before identifiers starting with `in` The automatic semicolon check treats a line starting with `in` or `instanceof` as a binary operator unless the next character is a letter. Digits, `_` and `$` also continue an identifier, so a line starting with `in_b`, `in1`, `in$` or `instanceof_` suppressed the semicolon and the statement failed to parse. Co-Authored-By: Claude Opus 5.5 --- src/scanner.c | 6 ++++-- test/corpus/semicolon_insertion.txt | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/scanner.c b/src/scanner.c index 795916dd..78ac80e1 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -26,6 +26,8 @@ static inline void advance(TSLexer *lexer) { lexer->advance(lexer, false); } static inline void skip(TSLexer *lexer) { lexer->advance(lexer, true); } +static inline bool is_identifier_char(int32_t c) { return iswalnum(c) || c == '_' || c == '$'; } + static bool scan_template_chars(TSLexer *lexer) { lexer->result_symbol = TEMPLATE_CHARS; for (bool has_content = false;; has_content = true) { @@ -199,7 +201,7 @@ static bool scan_automatic_semicolon(TSLexer *lexer, bool comment_condition, boo } skip(lexer); - if (!iswalpha(lexer->lookahead)) { + if (!is_identifier_char(lexer->lookahead)) { return false; } @@ -210,7 +212,7 @@ static bool scan_automatic_semicolon(TSLexer *lexer, bool comment_condition, boo skip(lexer); } - if (!iswalpha(lexer->lookahead)) { + if (!is_identifier_char(lexer->lookahead)) { return false; } break; diff --git a/test/corpus/semicolon_insertion.txt b/test/corpus/semicolon_insertion.txt index 75cca226..f7367245 100644 --- a/test/corpus/semicolon_insertion.txt +++ b/test/corpus/semicolon_insertion.txt @@ -130,6 +130,18 @@ a a instanceofX; +a + in_b; + +a + in1; + +a + in$; + +a + instanceof_; + --- (program @@ -146,6 +158,18 @@ a (expression_statement (binary_expression (identifier) (identifier))) + (expression_statement (identifier)) + (expression_statement (identifier)) + + (expression_statement (identifier)) + (expression_statement (identifier)) + + (expression_statement (identifier)) + (expression_statement (identifier)) + + (expression_statement (identifier)) + (expression_statement (identifier)) + (expression_statement (identifier)) (expression_statement (identifier)))