Milestone 3: lexer — scan.l port, base_yylex filter, Scan/SplitWithScanner/HashXXH3_64 - #3
Merged
Conversation
…anner/HashXXH3_64 Port the patched scan.l as a pull-based scanner in internal/lexer: all twelve flex start conditions (standard/extended/dollar/Unicode strings, quoted identifiers, bit/hex strings, nested C comments), the operator rule with its trailing +/- and embedded-comment truncation, the fourteen overlapping numeric-literal rules resolved by explicit longest-match candidate selection, keyword lookup against the generated tables, and scanner errors with the reference's exact messages, filenames, funcnames, and character-based cursor positions. Add the base_yylex token-merge filter (NOT_LA/NULLS_LA/WITH_LA/ WITHOUT_LA/FORMAT_LA, UIDENT/USCONST + UESCAPE resolution with str_udeescape) with unit tests pinning the pinned oracle's comment-blocks-merge behavior, and internal/xxh3 (XXH3_64bits_withSeed) verified against 126 oracle-generated vectors plus pg_query_go's three published ones. Wire parser.ScanToProtobuf, SplitWithScanner, and HashXXH3_64; retire their not-implemented stubs and guards. Gate met: all 43,373 scan-suite cases and all 8 split_scanner cases pass byte-identically; go test ./... green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AJQ7Jk1QEPsT5r7sFcfzEx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lands milestone 3 of PLAN.md: the lexer, with its oracle-backed acceptance gate met in full — all 43,373 scan-suite cases and all 8 split_scanner cases pass byte-identically against the pinned-oracle goldens, and are harvested out of the
metadata.jsontodo sidecars.What's in here
internal/lexer— thescan.lportA pull-based scanner (
Scanner.Next, one token per call likecore_yylex) covering all twelve flex start conditions: standard/extended/dollar-quoted/Unicode strings (with quote-continuation across newlines via the<xqs>lookahead), quoted identifiers, bit/hex strings, and nested C comments — plus the operator rule (trailing+/-stripping, embedded/*/--truncation, "operator too long"), keyword lookup against the generated tables, andSQL_COMMENT/C_COMMENTtokens per libpg_query's patches. Every production carries an attribution comment naming itsscan.lrule.The fourteen overlapping numeric-literal rules (
decinteger…real_junk) interact purely through flex's longest-match/rule-order discipline, including backtracking inside the*_junkrules (e.g.1_2$is trailing junk via the1+_2$split);numbers.goreproduces this by computing every candidate rule's match length and picking the winner.Scanner errors carry the reference's exact messages,
scan.lfilename,scanner_yyerror/core_yylexattribution, and character-based (not byte) cursor positions (pg_mbstrlen_with_lensemantics); the "at or near" text runs to the end of the current match, mirroring flex's hold-char NUL.base_yylexfilter (internal/lexer/filter.go)The token-merge layer from
parser.c:NOT_LA/NULLS_LA/WITH_LA/WITHOUT_LA/FORMAT_LAmerges, comment-token dropping, andUIDENT/USCONST+UESCAPEresolution with a fullstr_udeescapeport (surrogate pairs, escape-character validation, exact error cursors). Not exercised by this milestone's corpus (the parser consumes it from milestone 4), so it ships with unit tests — including one pinning a real pinned-oracle quirk verified against pg_query_go v6.2.2: a comment between a merge pair blocks the merge (the lookahead is a rawcore_yylexcall), soSELECT 1 WHERE 1 NOT /* c */ IN (2)is a syntax error in libpg_query where vanilla PostgreSQL accepts it.internal/xxh3Pure-Go
XXH3_64bits_withSeed(scalar paths, the only entry point the API needs), verified against pg_query_go's three published vectors plus 126 vectors generated from the pinned cgo oracle covering every length class (0 / 1–3 / 4–8 / 9–16 / 17–128 / 129–240 / hashLong incl. multi-block) with zero, small, and full-64-bit seeds.Public API wiring
parser.ScanToProtobuf(raw core-scanner tokens,Version170007, End offsets perpg_query_scan.c'syyllocendrules),parser.SplitWithScanner(pg_query_split.csemantics: top-level;terminators, keyword-bearing statements only, paren tracking), andparser.HashXXH3_64. Their not-implemented stubs and test guards are retired; the ported pg_query_goTestScansmoke test now runs, and new compat tests pin a full token stream, split behavior, and the published hash vectors.Validation
go test ./...green, including a-racerun over the corpusgo test ./parser -run TestCorpus -check-parsecmd/next-testnow points at the parse suite — milestone 4 (expressions + SELECT) is next.🤖 Generated with Claude Code
https://claude.ai/code/session_01AJQ7Jk1QEPsT5r7sFcfzEx
Generated by Claude Code