Skip to content

parser: ParseFile keeps the trivia the grammar never sees - #6

Merged
kyleconroy merged 1 commit into
mainfrom
claude/parsefile-trivia-pw47ve
Aug 25, 2026
Merged

parser: ParseFile keeps the trivia the grammar never sees#6
kyleconroy merged 1 commit into
mainfrom
claude/parsefile-trivia-pw47ve

Conversation

@kyleconroy

Copy link
Copy Markdown
Contributor

sqlc fmt's SQLite reprinter needs the comments the grammar never sees, and until now it recovered them by lexing the source a second time with its own scanner. This exposes them from the single lexer pass parsing already makes, so the formatter's statements and comments come from one pass and one lexical truth.

API (additive)

  • lexer.LexFile(src) (tokens, trivia []token.Token) — the tokens Lex returns today, together with the runs of whitespace and comments Lex drops, as SPACE/COMMENT tokens in source order. Lex is now a thin wrapper over the shared core; its behavior is unchanged.
  • parser.ParseFile(src) (*File, error) and the Options form, with File{Stmts, Trivia}. Same grammar, same token stream, same bail/recover shape as the existing entry points.

"Trivia" is Roslyn's term — the C# compiler calls the channel of source text that does not affect syntax "syntax trivia", and swift-syntax and rust-analyzer use the same name. The doc comments on LexFile and File.Trivia carry the attribution.

Tests

Two corpus-wide properties pin the contract, run over every case via forEachCorpusCase:

  • Tiling: tokens and trivia tile the consumed input exactly — ordered, no gap, no overlap, no byte belonging to neither — and trivia holds only SPACE and COMMENT runs.
  • Agreement: ParseFile matches ParseString on every case's statements (reflect.DeepEqual) and errors.

Plus a focused lexer.LexFile unit test covering line/block/unterminated comments, quoted regions, and empty input. Full suite passes.

Downstream

sqlc's sqlite engine already consumes this from a pseudo-version pin of this branch (sqlc-dev/sqlc branch claude/sqlc-fmt-formatting-pw47ve), deleting its duplicate scanner. After merge, a tag (v0.2.0 fits — additive) lets sqlc pin the release instead.

🤖 Generated with Claude Code

https://claude.ai/code/session_018MTvpHqNMadH12pTtsgUq2


Generated by Claude Code

lexer.LexFile returns the tokens Lex returns today together with the
runs of whitespace and comments Lex drops, from the single pass Lex
already makes. parser.ParseFile parses a script and carries that trivia
on the new File result, so a consumer that needs both — a formatter
putting comments back where they came from — no longer lexes the input
twice.

"Trivia" is Roslyn's term: the C# compiler calls the channel of source
text that does not affect syntax "syntax trivia", and swift-syntax and
rust-analyzer use the same name.

Two corpus-wide properties pin the contract: tokens and trivia tile the
consumed input exactly (ordered, no gap, no overlap), and ParseFile
agrees with ParseString on every case's statements and errors. Existing
entry points are unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018MTvpHqNMadH12pTtsgUq2
@kyleconroy
kyleconroy merged commit 59b2dbf into main Aug 25, 2026
1 check 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.

2 participants