refactor: improve hash implementations for Item, State, and Token#38
Merged
Conversation
Pytest ReportTest Results
Comment by ✨sambyeol/publish-pytest-action |
Pytest ReportTest Results
Comment by ✨sambyeol/publish-pytest-action |
henrylee97
enabled auto-merge (squash)
May 10, 2026 16:01
Super-linter summary
All files and directories linted successfully For more information, see the GitHub Actions workflow run Powered by Super-linter |
henrylee97
added a commit
that referenced
this pull request
May 11, 2026
## Summary - Fix hash semantics for `Item`, `State`, and `Token` to be value-based and class-aware - Replace recursive FIRST/FOLLOW computation with worklist fixed-point algorithms, fixing incorrect results on mutually recursive grammars - Make LR(0) state construction deterministic across repeated `Parser` instantiations - Add English docstrings and SLR(1) algorithm comments throughout the codebase - Expand test coverage with 4 new test modules (safety-net, FIRST/FOLLOW, determinism, hash semantics) ## Changes ### Bug Fixes - Correct hash implementations for `Item`, `State`, `Token` (#38) - Fixed-point FIRST / FOLLOW computation replacing re-entry-guard recursion (#36) ### Improvements - Deterministic LR(0) state construction (#37) ### Documentation - English docstrings and SLR(1) inline algorithm comments (#34) ### Tests - Parser safety-net suite, FIRST/FOLLOW unit tests, determinism tests, hash semantics tests (#35 #36 #37 #38) ### Maintenance - Bumped GitHub Actions: `actions/checkout` 4→6, `actions/setup-python` 5→6, `sambyeol/publish-pytest-action` 2→4, `super-linter/super-linter` 7→8 (#28 #29 #31 #32 #33) ## Test plan - [x] `pytest -q` passes (`29 passed, 2 xfailed`) - [x] `python examples/calc/calc.py examples/calc/data/ex01.calc` prints `2` Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
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.
Summary
Item.__hash__: sum-based → tuple-based (hash((self.left, tuple(self.right), self.loc))).Fixes an order-insensitivity bug where
[A, B]and[B, A]in the RHS produced equal hashes.State.__hash__: sum-based → frozenset-based (hash(frozenset(self.items))),consistent with the
frozenset[Item]cache key already used byintern_state(T3).Token.__hash__: now includestype(self)—hash((type(self), self.lineno, self.offset)).The equality contract already incorporates the class via
isinstance(other, self.__class__);the hash now matches. Added one sentence to the docstring to make this explicit.
Existing subclass overrides (
hash(self.value) + super().__hash__()) remain correct.Tests
Added
tests/test_hash_semantics.py(5 tests):test_item_equal_data_hash_equal— independently constructed equal Items are==and share a hashtest_item_different_right_order_hash_different— validates the tuple-based fixtest_state_equal_items_hash_equal— equal item sets produce equal State hashestest_token_hash_includes_class— different subclasses at the same position hash differentlytest_token_same_class_same_position_equal— regression: same class + position → equalResult
29 passed, 2 xfailed— pyright clean, black/isort unchanged.