Skip to content

fix: keep glued lexemes intact when formatting - #36

Merged
emrberk merged 1 commit into
masterfrom
fix/formatter-glued-lexemes
Sep 24, 2026
Merged

emrberk merged 1 commit into
masterfrom
fix/formatter-glued-lexemes

Conversation

@emrberk

@emrberk emrberk commented Sep 24, 2026

Copy link
Copy Markdown
Member

Problem

The formatter inserted a space between two word tokens that the lexer split from one QuestDB lexeme. The lexer never errors on these, so the "leave unknown text alone" path never ran.

Input Output
0x1F 0 x1F
16777217.0f 16777217.0 f
geohash(5c) geohash(5 c)
1500ns 1500n s

SELECT id, 0x1F FROM t formatted, ran green, and returned INT 0 in a column named x1F. Geohash DDL failed with "invalid GEOHASH size".

Fix

  • spacing.ts: two word pieces with no whitespace between them in the source keep no gap. The dot rule treats any digit-led token as a number, so t. 5m no longer becomes the single token .5m.
  • layout.ts: all phrase matching goes through one guard. A clause never starts on a word glued to the previous word, so 10.5mFROM no longer gets a newline inside it.

Two word tokens with no whitespace between them are never two lexemes in SQL. The rule closes hex, float suffixes, geohash precision, nanosecond durations, and future suffixes without listing literal shapes.

Tests

  • oracles.ts: assertPreserved gains two oracles. Whitespace-stripped equality catches insertions. Main-lexer token equality catches merges. The existing stream oracle uses the formatter's own lexer, so it split 0x1F the same way on both sides and could not see this.
  • lexemes.test.ts: eleven split lexemes in seven contexts, and an exhaustive sweep of 82 lexemes in every pair with three separators.

A random fuzzer over the same alphabet, 60,000 inputs on three seeds, reports zero character or lexeme changes after the fix. Before the fix it reported 353 extra failures.

🤖 Generated with Claude Code

The formatter inserted a space between two word tokens that the lexer
split from one QuestDB lexeme: 0x1F became 0 x1F, 16777217.0f became
16777217.0 f, geohash(5c) became geohash(5 c). Some of those formatted
queries ran and returned different results.

Two word pieces with no whitespace between them in the source now keep
no gap, and no clause starts on such a piece. A dot stays apart from
any digit-led token, not only NumberLiteral, so `t. 5m` does not become
the single token `.5m`.

Two new oracles guard this: whitespace-stripped equality catches
insertions, and main-lexer token equality catches merges. A new test
sweeps every pair of 82 lexemes with three separators.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@emrberk
emrberk merged commit cd18910 into master Sep 24, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant