Skip to content

Apply design patterns across packages: shared scanner loop, polymorphic criteria nodes, label dispatch, split SLR parser - #3

Merged
m-messer merged 4 commits into
mainfrom
refactor/design-patterns
Oct 16, 2026
Merged

m-messer merged 4 commits into
mainfrom
refactor/design-patterns

Conversation

@m-messer

Copy link
Copy Markdown
Member

Four behaviour-preserving refactors from a design-pattern review of the packages. Each is one commit and can be reviewed (or reverted) on its own. Public behaviour is unchanged; the one API change is noted under slr_parsing.

Changes

  • expression_parsing: one span-rewriting loop. _replace_command, sanitise_latex and normalise_unicode_operators each repeated the same find/copy/replace loop. They now pass a finder to _scanning.replace_matches. substitute (hot path with a first-character index), _protect_e_symbols (token-based) and units' _replace_prefix (another package) are left as they were.
  • criteria: node kinds own their rules. Each node class sets KIND and STYLE and implements copy_into(graph) and check_target(target). That replaces the isinstance chains in CriteriaGraph.add_node, CriteriaGraph.attach and tree._tree_node. Error messages are unchanged.
  • units: unit LaTeX by label, tag rules as a match.
    • The unit LaTeX renderers are module functions selected by a _UNIT_LATEX table.
    • quantity_tag_handler is a match on the label, using a leaf-tag table and named predicates (_is_unit_power, _is_reciprocal_unit, _is_number_ratio).
    • Moving strict juxtaposition into its own reduction action was tried and backed out: rotation relies on re-tagging to strip units, and without it strict kg 2x reported a garbled extra reverted unit. A new regression test pins the current reverted_units for those inputs.
  • slr_parsing: SLRParser split into scanner, table and driver.
    • Scanner (scanner.py) turns text into tokens.
    • ParseTable (table.py) holds the FIRST and FOLLOW sets, the LR(0) states and the rows.
    • SLRParser keeps its constructor and methods and runs the parse.
    • API change: table entries are typed: Shift, Reduce, Accept, Reject and Recover, exported with an Entry union. They replace the integer encoding. parsing_table_to_string() output is unchanged.
    • The entry classes are @final, and the driver tells them apart with type(...) is checks: match made parse() 8–10% slower.

Verification

  • ruff, format and mypy are clean, and all four test suites pass.
  • tools/parity/check.py: 0 unexpected changes.
  • parsing_table_to_string() output is byte-identical before and after for the criteria, convention and quantity parsers.
  • A dump of every quantity's tags and outputs over the parity corpus plus extra juxtaposition inputs, in both strict and natural mode, is byte-identical before and after.
  • Speed, measured against a clean worktree of main with runs interleaved:
    • parse() alone is about 2–3% faster.
    • Scanning and parsing end to end are unchanged.
    • Building a parser is about 0.03 ms slower, and parsers are cached.
  • scripts/check_dist.py passes.

Followed by the stacked PR for PhysicalQuantity (refactor/physical-quantity).

🤖 Generated with Claude Code

…tility, improve consistency across scanners
- Introduce `KIND` and `STYLE` as class variables for node types.
- Centralize node copying logic with `copy_into` methods in node classes.
- Generalize edge validation via `check_target`.
- Simplify `add_node` and edge attachment logic in `CriteriaGraph`.
- Merge node shape definitions into `nodes.py`.
…IT_LATEX` lookup, and refactor subtree tagging logic in node label parsing.
…o use typed parse-table entries, and adjust related tests, documentation, and changelog.
@m-messer
m-messer merged commit bccfd2c into main Oct 16, 2026
8 checks passed
@m-messer
m-messer deleted the refactor/design-patterns branch October 16, 2026 08:32
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