Skip to content

feat(parser): error reporting, API cleanup, and FOLLOW removal#45

Merged
henrylee97 merged 11 commits into
masterfrom
task/t7-error-reporting
May 12, 2026
Merged

feat(parser): error reporting, API cleanup, and FOLLOW removal#45
henrylee97 merged 11 commits into
masterfrom
task/t7-error-reporting

Conversation

@henrylee97

Copy link
Copy Markdown
Member

Summary

  • Remove dead FOLLOW infrastructure: compute_follow_sets, Rule.calc_follow,
    Rule.calc_first, and all related attributes are deleted. Since T6, LALR(1)
    per-item lookaheads drive all reduce decisions; FOLLOW sets are no longer needed.
    Phase numbering updated (old 4→3, 5→4, 6→5).

  • Table API cleanup: force_update renamed to resolve_conflict (makes intent
    explicit). New Table.expected_tokens(state) helper returns the terminal classes
    valid in a given state.

  • Structured exceptions: LexingError and ParsingError now carry lineno,
    offset, and (for ParsingError) the offending token and an expected list of
    valid token classes. Both format as "Line X, col Y: <message>". Parser.parse
    tracks last_token to provide position context even on end-of-input errors.

  • FOLLOW references removed from docs/comments: All mentions of FOLLOW sets in
    docstrings, comments, and test descriptions replaced with per-item lookahead
    language. LALR(1)-only test functions renamed from follow_inflation to
    resolves_rr_conflict.

Test plan

  • pytest -q — 38 passed, 0 xfailed
  • pyright — 0 errors
  • black --check . and isort --check . — clean
  • test_error_reporting.py — 6 new tests asserting ParsingError/LexingError
    field values and str() format

henrylee97 and others added 11 commits May 12, 2026 14:12
…ases

Rule.follow, Rule.follow_built, Rule.calc_first, Rule.first, Rule.first_built,
Rule.calc_follow, and compute_follow_sets are removed.  Since T6 the LALR(1)
lookahead table drives all reduce decisions; FOLLOW sets were no longer used.

Phase numbering updated: old Phase 4→3, 5→4, 6→5.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ed_tokens

Table.force_update renamed to Table.resolve_conflict to make the intent
explicit: it is only called after a conflict has been decided, not for
arbitrary table overwrites.

Table.expected_tokens(state) is a new helper that returns the terminal
classes with an action in a given state.  It will be used by Parser.parse
to populate ParsingError.expected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… ParsingError

LexingError gains __init__(message, lineno, offset) and a __str__ that
formats as "Line X, col Y: <message>".

ParsingError gains __init__(message, token, lineno, offset, expected) and
a matching __str__.  Both errors use the same "Line X, col Y:" prefix so
callers can parse error output uniformly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d tokens

Parser.parse now tracks last_token to carry position context into the
end-of-input error.  All three ParsingError raise sites pass the offending
token (or None for EOF), lineno, offset, and the list of expected terminal
classes for the current state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Six tests cover:
- ParsingError.token, .lineno, .offset, .expected on unexpected token
- str(ParsingError) contains "Line X, col Y:" prefix and expected class name
- ParsingError.expected is non-empty when input is truncated
- LexingError.lineno, .offset, .message fields
- str(LexingError) "Line X, col Y:" format

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove redundant issubclass in Table.expected_tokens (isinstance(sym, type)
already narrows Symbol to type[Token]).  Remove redundant isinstance in the
case _ fallthrough (token is already Token at that point).

Add GrammarEntry type alias to test_error_reporting.py so the GRAMMAR dict
is fully typed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The LALR(1) implementation no longer uses FOLLOW sets; reduce actions fire
on per-item lookaheads computed by ASU §9.6.  Remove the SLR(1)-vs-LALR(1)
comparison phrasing that mentioned FOLLOW.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace FOLLOW set computations and SLR(1)-vs-LALR(1) comparisons in the
section header and two test docstrings with plain descriptions of the
per-item lookahead behaviour.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…r_conflict

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…port

No circular dependency exists between exception.py and token.py.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@henrylee97 henrylee97 self-assigned this May 12, 2026
@henrylee97 henrylee97 added the enhancement New feature or request label May 12, 2026
@github-actions

Copy link
Copy Markdown

Pytest Report

Test Results

  • Tests: 38
  • Errors: 0
  • Failures: 0
  • Skipped: 0

Comment by ✨sambyeol/publish-pytest-action

@github-actions

Copy link
Copy Markdown

Pytest Report

Test Results

  • Tests: 38
  • Errors: 0
  • Failures: 0
  • Skipped: 0

Comment by ✨sambyeol/publish-pytest-action

@henrylee97 henrylee97 added the refactor Code changes that improve structure without altering behavior label May 12, 2026
@henrylee97
henrylee97 enabled auto-merge (squash) May 12, 2026 14:45
@github-actions

Copy link
Copy Markdown

Super-linter summary

Language Validation result
PYTHON_BLACK Pass ✅
PYTHON_ISORT Pass ✅
YAML Pass ✅

All files and directories linted successfully

For more information, see the GitHub Actions workflow run

Powered by Super-linter

@henrylee97
henrylee97 merged commit 807a3d2 into master May 12, 2026
7 checks passed
@henrylee97
henrylee97 deleted the task/t7-error-reporting branch May 12, 2026 14:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request refactor Code changes that improve structure without altering behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant