Skip to content

feat: frontier/expected-set for error localization (#467 step 3)#470

Open
SJrX wants to merge 1 commit into
issue-345-2from
issue-345-3
Open

feat: frontier/expected-set for error localization (#467 step 3)#470
SJrX wants to merge 1 commit into
issue-345-2from
issue-345-3

Conversation

@SJrX

@SJrX SJrX commented Jun 21, 2026

Copy link
Copy Markdown
Owner

What

Adds a frontier: a high-water-mark recorder threaded through parse() so that even when no path matches, we know where parsing got stuck and what was expected there.

Stacked on #469 (issue-345-2). This PR's diff is the Frontier type, the one extra (defaulted) parse() parameter threaded through the combinators, and the updated validate()/tests.

The problem it fixes

parse() only returns successful matches, so a malformed value's failing paths vanish and we lose how far we got. For AF_INET, AF_INET6 against the real grammar Seq( …family-list… , EOF() ):

  1. the family-list consumes AF_INET and stops at the comma (offset 7);
  2. the outer Seq tries EOF() at 7, which matches nothing → the whole Seq yields an empty sequence;
  3. validate()'s maxOfOrNull { it.end } over an empty sequence → furthest = 0.

The "we reached offset 7" fact existed for a moment and was thrown away. (This is the limitation that was pinned with a furthest == 0 assertion in #469.)

How the frontier works

A small mutable Frontier rides along through parse() (one extra parameter, defaulted so the 2-arg call still works). Every leaf matcher — the terminals and EOF — reports itself when consulted at an offset. The frontier keeps only the deepest offset reached and the set of matchers wanted there. Combinators just thread the same instance into their children; they don't record.

validate() reads it: SyntaxError now carries (furthest, expected).

One mechanism, two payoffs

Scope / notes

  • The old SyntacticMatch/SemanticMatch engine and GrammarOptionValue are untouched; full suite is green.
  • The expected set is typed Set<Combinator> (so EOF can appear alongside terminals); a real completion contributor would map these to lookup strings (e.g. a LiteralChoiceTerminal's choices) — that's the next step, not this one.
  • Still not wired into IntelliJ; the path-cap + cancellation hook remain prerequisites before that.

Refs #467 #345 #343

🤖 Generated with Claude Code

…step 3)

parse() only returns successful matches, so when a value is malformed the failing
paths vanish and we lose how far we got — e.g. for "AF_INET, AF_INET6" the outer
Seq(..., EOF()) drops the partial path when EOF fails at the comma, and the
reported furthest collapsed to 0.

Add a Frontier: a high-water-mark recorder threaded through parse() (one extra,
defaulted parameter so the 2-arg call still works). Every leaf matcher (terminals
and EOF) reports itself when consulted at an offset; the Frontier keeps only the
deepest offset reached and the set of matchers expected there. validate() now
reports SyntaxError(furthest, expected) from it.

This is one mechanism with two payoffs:
- error localization: "AF_INET, AF_INET6" now reports furthest=7 (the comma) and
  expected={whitespace, end-of-input};
- the seed of completion (#343): the expected set at a position is exactly "what
  could come next here" — a new test shows the empty value expects "none", "~",
  or an address-family name.

Combinators thread the shared frontier into their children; only the leaf matchers
record. The old SyntacticMatch/SemanticMatch engine and GrammarOptionValue are
untouched; full suite green.

Refs #467 #345 #343

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Test Results

1 118 tests  +1   1 118 ✅ +1   49s ⏱️ ±0s
  295 suites ±0       0 💤 ±0 
  295 files   ±0       0 ❌ ±0 

Results for commit 6a8c012. ± Comparison against base commit c3b8f6d.

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