You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Consolidated triage of open issues, the fixes prepared in this wave, and a performance assessment of the parser. Baseline before any changes: npm ci, npm run build (jison) and jest (58/58) all green on Node 22.
Open issues
Issue
Title
Category
Addressed-by-PR
—
No open issues at time of triage (2026-07-06)
—
—
With an empty tracker, this wave focused on defects found by inspecting and profiling the lexer/grammar. All are draft PRs:
Characters the lexer cannot match are echoed to stdout and silently dropped (%options flex default rule), so invalid input can "successfully" parse to wrong quads
IRIREF rejects = inside IRIs (stray ANTLR ~ plus erroneous = in the negated class); <http://example.org/s?x=1> fails with a misleading "Unknown prefix: http"
addList assigns to an undeclared head, leaking a global term object whenever a list is emitted, and breaking under strict mode
fix
Pre-existing open PRs, for completeness: #185 (dependabot: jest 29 -> 30) and #134 (your WIP @name/@description).
Performance findings
Benchmark: synthetic 66 KB / 7,501-quad document (300 shapes x 5 property constraints), Node 22, on a noisy 2-core box shared with a live server — numbers are indicative only.
Baseline main: median 335 ms per parse (~22K quads/s). --cpu-prof shows >55% of self time inside the generated PNAME_LN/PNAME_NS regexes: the PN_CHARS*/HEX macros are alternations of one-element character classes, and %options flex runs every rule's regex at every token position.
Further candidates, descending value — all need more care than a low-risk wave allows:
Drop %options flex and reorder rules for first-match semantics. Likely another significant win, but it changes token precedence (INTEGER vs DECIMAL/DOUBLE, keyword vs PNAME overlaps) and needs careful rule ordering plus extra precedence tests.
Remove the leftover debug assertion in emit() (p.value.includes(',') string scan plus a boo ... error on every quad) — small win, and that error message should not ship as-is anyway.
Cache namedNode terms for constant IRIs (rdf:first/rest/nil, sh:* are rebuilt via string concat per emission) — modest allocation win; interacts with the swappable Parser.factory, so needs a decision on custom-factory support.
Needs your decision
%options flex removal (perf item 1): worthwhile but semantically riskier than this wave's changes — your call on acceptable risk and required test coverage.
%options case-insensitive: keywords (shape, BASE, true, parameter names...) currently match case-insensitively, which is more lenient than the SHACL-C spec. Intentional?
Leftover debug artifacts: throw new Error('b') in addList and the boo ... validation in emit() — happy to remove or replace with meaningful messages in a follow-up.
Broken-but-unused COMMENT macro: '#' ~[\r\n]* compiles to #[\r\n]* (ANTLR negation silently dropped); the first whitespace/comment rule does the real work. Cleanup candidate together with the unused PASS/WS/escapeSequence/toInt definitions.
index.d.ts omits the exported Parser class (only parse is declared). Small DX fix if wanted.
Stale branches: fix/relative-iris (its test cases now pass on main), wip/lots-of-logging, jeswr-patch-1 — deletion candidates.
Review timing: prepared with Claude; @jeswr will personally review before it progresses — expect active review Wed-Fri.
Consolidated triage of open issues, the fixes prepared in this wave, and a performance assessment of the parser. Baseline before any changes:
npm ci,npm run build(jison) and jest (58/58) all green on Node 22.Open issues
With an empty tracker, this wave focused on defects found by inspecting and profiling the lexer/grammar. All are draft PRs:
ex:a_bparses asex:a;ex:_abfails) — jison-lex appends\bto the quoted'_'literal inPN_CHARS_U%options flexdefault rule), so invalid input can "successfully" parse to wrong quadsIRIREFrejects=inside IRIs (stray ANTLR~plus erroneous=in the negated class);<http://example.org/s?x=1>fails with a misleading "Unknown prefix: http"addListassigns to an undeclaredhead, leaking a global term object whenever a list is emitted, and breaking under strict modePre-existing open PRs, for completeness: #185 (dependabot: jest 29 -> 30) and #134 (your WIP
@name/@description).Performance findings
Benchmark: synthetic 66 KB / 7,501-quad document (300 shapes x 5 property constraints), Node 22, on a noisy 2-core box shared with a live server — numbers are indicative only.
--cpu-profshows >55% of self time inside the generatedPNAME_LN/PNAME_NSregexes: thePN_CHARS*/HEXmacros are alternations of one-element character classes, and%options flexruns every rule's regex at every token position.parseloop ~25%, lexernext()~25% (flex mode still iterates all ~50 rules per token even once the regexes are cheap), GC ~13%,index.jsglue ~6%; all regexes combined ~3%.Further candidates, descending value — all need more care than a low-risk wave allows:
%options flexand reorder rules for first-match semantics. Likely another significant win, but it changes token precedence (INTEGERvsDECIMAL/DOUBLE, keyword vs PNAME overlaps) and needs careful rule ordering plus extra precedence tests.emit()(p.value.includes(',')string scan plus aboo ...error on every quad) — small win, and that error message should not ship as-is anyway.namedNodeterms for constant IRIs (rdf:first/rest/nil,sh:*are rebuilt via string concat per emission) — modest allocation win; interacts with the swappableParser.factory, so needs a decision on custom-factory support.Needs your decision
%options flexremoval (perf item 1): worthwhile but semantically riskier than this wave's changes — your call on acceptable risk and required test coverage.%options case-insensitive: keywords (shape,BASE,true, parameter names...) currently match case-insensitively, which is more lenient than the SHACL-C spec. Intentional?throw new Error('b')inaddListand theboo ...validation inemit()— happy to remove or replace with meaningful messages in a follow-up.n3Parser._resolveIRI,_setBaseand_lexer._unescape. Dependabot bumps n3 regularly (chore(deps): bump n3 from 2.0.3 to 2.0.4 #187/chore(deps): bump n3 from 2.0.4 to 2.1.0 #190/chore(deps): bump n3 from 2.1.0 to 2.1.1 #191) and nothing checks these internals at compile time; consider vendoring the IRI-resolution/unescape logic or adding an explicit smoke test for them.COMMENTmacro:'#' ~[\r\n]*compiles to#[\r\n]*(ANTLR negation silently dropped); the first whitespace/comment rule does the real work. Cleanup candidate together with the unusedPASS/WS/escapeSequence/toIntdefinitions.index.d.tsomits the exportedParserclass (onlyparseis declared). Small DX fix if wanted.fix/relative-iris(its test cases now pass on main),wip/lots-of-logging,jeswr-patch-1— deletion candidates.Review timing: prepared with Claude; @jeswr will personally review before it progresses — expect active review Wed-Fri.