Whole file
lark-parser/lark
The author described this change as “Fix types for tree_templates, better error messages”. It counts as a record because the check below fails on the code as it stood at 66c22d001 and passes on 242c4a574, with nothing else changed between the two runs.
Projectlark-parser/lark
Fix saved2022-05-24
Sharing licenceMIT · LICENSE
Change size+15 −5
What the code was meant to do, written into the code itself as a save note
Fix types for tree_templates, better error messages
The change
| 9 | 9 | from lark import Tree, Transformer | |
| 10 | 10 | from lark.exceptions import MissingVariableError | |
| 11 | 11 | ||
| 12 | + | Branch = Union[Tree[str], str] | |
| 12 | 13 | TreeOrCode = Union[Tree[str], str] | |
| 14 | + | MatchResult = Dict[str, Tree] | |
| 13 | 15 | _TEMPLATE_MARKER = '$' | |
| 14 | 16 | ||
| 15 | 17 | ||
| ⋯ | |||
| 17 | 19 | """Template Configuration | |
| 18 | 20 | ||
| 19 | 21 | Allows customization for different uses of Template | |
| 22 | + | ||
| 23 | + | parse() must return a Tree instance. | |
| 20 | 24 | """ | |
| 21 | 25 | ||
| 22 | 26 | def __init__(self, parse=None): | |
| ⋯ | |||
| 49 | 53 | assert self._parse | |
| 50 | 54 | template = self._parse(template) | |
| 51 | 55 | ||
| 52 | - | assert isinstance(template, Tree) | |
| 56 | + | if not isinstance(template, Tree): | |
| 57 | + | raise TypeError("template parser must return a Tree instance") | |
| 58 | + | ||
| 53 | 59 | return template | |
| 54 | 60 | ||
| 55 | 61 | def __call__(self, template: Tree[str]) -> 'Template': | |
| 56 | 62 | return Template(template, conf=self) | |
| 57 | 63 | ||
| 58 | - | def _match_tree_template(self, template: TreeOrCode, tree: TreeOrCode) -> Optional[Dict[str, TreeOrCode]]: | |
| 64 | + | def _match_tree_template(self, template: TreeOrCode, tree: Branch) -> Optional[MatchResult]: | |
| 65 | + | """Returns dict of {var: match} if found a match, else None | |
| 66 | + | """ | |
| 59 | 67 | template_var = self.test_var(template) | |
| 60 | 68 | if template_var: | |
| 69 | + | if not isinstance(tree, Tree): | |
| 70 | + | raise TypeError(f"Template variables can only match Tree instances. Not {tree}") | |
| 61 | 71 | return {template_var: tree} | |
| 62 | 72 | ||
| 63 | 73 | if isinstance(template, str): | |
| ⋯ | |||
| 100 | 110 | ||
| 101 | 111 | ||
| 102 | 112 | class Template: | |
| 103 | - | """Represents a tree templates, tied to a specific configuration | |
| 113 | + | """Represents a tree template, tied to a specific configuration | |
| 104 | 114 | ||
| 105 | 115 | A tree template is a tree that contains nodes that are template variables. | |
| 106 | 116 | Those variables will match any tree. | |
| ⋯ | |||
| 111 | 121 | self.conf = conf | |
| 112 | 122 | self.tree = conf._get_tree(tree) | |
| 113 | 123 | ||
| 114 | - | def match(self, tree: TreeOrCode) -> Optional[Dict[str, TreeOrCode]]: | |
| 124 | + | def match(self, tree: TreeOrCode) -> Optional[MatchResult]: | |
| 115 | 125 | """Match a tree template to a tree. | |
| 116 | 126 | ||
| 117 | 127 | A tree template without variables will only match ``tree`` if it is equal to the template. | |
| ⋯ | |||
| 127 | 137 | tree = self.conf._get_tree(tree) | |
| 128 | 138 | return self.conf._match_tree_template(self.tree, tree) | |
| 129 | 139 | ||
| 130 | - | def search(self, tree: TreeOrCode) -> Iterator[Tuple[Tree[str], Dict[str, TreeOrCode]]]: | |
| 140 | + | def search(self, tree: TreeOrCode) -> Iterator[Tuple[Tree[str], MatchResult]]: | |
| 131 | 141 | """Search for all occurances of the tree template inside ``tree``. | |
| 132 | 142 | """ | |
| 133 | 143 | tree = self.conf._get_tree(tree) | |
The check that tells the two apart
fail→pass·tests/test_tree_templates.py::TestTreeTemplatesConf::test_template_match__only_tree
Check file tests/test_tree_templates.py, taken without changes from the fix and copied onto the older code, so the exact same check runs against both versions.
Origin and history
The code before it66c22d0019170ad4d6bfb45e881776e0dad32625
Broken version dated2022-05-24
Modulelark.tree_templates
Units changedTemplate, TemplateConf
Fingerprint83d9d0d77f91583e
Checked2026-08-18 by goldset/0.1
Every field above is generated by our program. None of it is written by hand.
Other bugs found in lark-parser/lark
- 2026-07-08Fix lexer_callbacks silently dropped for keyword terminals
- 2026-06-24Transformer_NonRecursive
- 2026-06-04Raise GrammarError for non-terminal names in %declare
- 2026-06-02Fix empty SPPF node from xearley ignore carry-over (fixes #1598)
- 2026-05-24fix: raise GrammarError for template usage inside terminals
- 2024-10-25Adjust behaviour in #1481 to raise a NotImplementedError