Skip to content

refactor(grammar): modernize string formatting with f-strings and improve type hinting - #1635

Open
ardozcnn wants to merge 4 commits into
lark-parser:masterfrom
ardozcnn:master
Open

refactor(grammar): modernize string formatting with f-strings and improve type hinting#1635
ardozcnn wants to merge 4 commits into
lark-parser:masterfrom
ardozcnn:master

Conversation

@ardozcnn

Copy link
Copy Markdown

Replaced legacy % string formatting across Symbol, Terminal, RuleOptions, and Rule classes with modern Python f-strings.

Added missing type hints for method parameters (other: Any, memo: Optional[Dict], f: Callable) and return types (-> None, -> str, -> int).

Included empty_indices in RuleOptions.repr to accurately reflect all initialization parameters.

Formatted tuple entries in serialize_fields consistently.

@erezsh

erezsh commented Aug 12, 2026

Copy link
Copy Markdown
Member

Overall looks okay. You can use tox to run the type checker with the official configuration.

@ardozcnn ardozcnn left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

@ardozcnn

Copy link
Copy Markdown
Author

I ran the code can you check?

@erezsh

erezsh commented Aug 25, 2026

Copy link
Copy Markdown
Member

Opus says (and I agree):

  1. NonTerminal.serialize — the memo hint is wrong. memo is never a dict; it's a SerializeMemoizer (see Serialize.memo_serialize, and _serialize in utils.py, which already types it that way). mypy doesn't catch it because the base method leaves memo implicitly Any. Please use Optional[SerializeMemoizer], or Any to match lalr_parser.py.

  2. renamed should return Self, not Symbol. The body is type(self)(...), so NonTerminal.renamed() returns a NonTerminal. Annotating it Symbol makes correct code fail to typecheck — e.g. rule.origin = rule.origin.renamed(f) errors with "expression has type Symbol, variable has type NonTerminal". It slips through today only because the single caller (load_grammar.py:1053) is in an untyped context.

We support Python 3.8 and have no runtime dependencies, so import it the way common.py already does:

if TYPE_CHECKING:
if sys.version_info >= (3, 11):
from typing import Self
else:
from typing_extensions import Self

@ardozcnn

Copy link
Copy Markdown
Author

Thanks for the detailed review! I've updated renamed() to return Self (handled via TYPE_CHECKING for Python 3.8 compatibility) and changed memo in NonTerminal.serialize to Any as suggested.

@erezsh

erezsh commented Aug 27, 2026

Copy link
Copy Markdown
Member

You accidentally deleted the ###} comments that are needed for the standalone parser.

added ###}
@ardozcnn

Copy link
Copy Markdown
Author

Sorry about that! I've restored the ###} comment for the standalone parser. Thanks for the review

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.

2 participants