Skip to content

Commit 2c73642

Browse files
committed
Small fix, comments, added some types
1 parent 2646ca4 commit 2c73642

2 files changed

Lines changed: 24 additions & 19 deletions

File tree

lark/lark.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,15 +273,15 @@ class Lark(Serialize):
273273
parser: 'ParsingFrontend'
274274
terminals: Collection[TerminalDef]
275275

276-
__serialize_fields__ = 'parser', 'rules', 'options'
276+
__serialize_fields__ = ['parser', 'rules', 'options']
277277

278278
def __init__(self, grammar: 'Union[Grammar, str, IO[str]]', **options) -> None:
279279
self.options = LarkOptions(options)
280280
re_module: types.ModuleType
281281

282282
# Update which fields are serialized
283283
if self.options.cache_grammar:
284-
self.__serialize_fields__ = self.__serialize_fields__ + ('grammar',)
284+
self.__serialize_fields__ = self.__serialize_fields__ + ['grammar']
285285

286286
# Set regex or re module
287287
use_regex = self.options.regex
@@ -414,7 +414,7 @@ def __init__(self, grammar: 'Union[Grammar, str, IO[str]]', **options) -> None:
414414
raise ConfigurationError("invalid ambiguity option: %r. Must be one of %r" % (self.options.ambiguity, _VALID_AMBIGUITY_OPTIONS))
415415

416416
if self.options.parser is None:
417-
terminals_to_keep = '*'
417+
terminals_to_keep = '*' # For lexer-only mode, keep all terminals
418418
elif self.options.postlex is not None:
419419
terminals_to_keep = set(self.options.postlex.always_accept)
420420
else:

lark/tree_matcher.py

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
"""Tree matcher based on Lark grammar"""
22

33
import re
4+
from typing import List, Dict
45
from collections import defaultdict
56

6-
from . import Tree, Token
7+
from . import Tree, Token, Lark
78
from .common import ParserConf
89
from .exceptions import ConfigurationError
910
from .parsers import earley
@@ -40,7 +41,7 @@ def _best_from_group(seq, group_key, cmp_key):
4041
return list(d.values())
4142

4243

43-
def _best_rules_from_group(rules):
44+
def _best_rules_from_group(rules: List[Rule]) -> List[Rule]:
4445
rules = _best_from_group(rules, lambda r: r, lambda r: -len(r.expansion))
4546
rules.sort(key=lambda r: len(r.expansion))
4647
return rules
@@ -86,19 +87,23 @@ class TreeMatcher:
8687
8788
Initialize with an instance of Lark.
8889
"""
90+
rules_for_root: Dict[str, List[Rule]]
91+
rules: List[Rule]
92+
parser: Lark
8993

90-
def __init__(self, parser):
94+
def __init__(self, parser: Lark):
9195
# XXX TODO calling compile twice returns different results!
9296
assert not parser.options.maybe_placeholders
9397

94-
# XXX TODO: we just ignore the potential existence of a postlexer
95-
if parser.options.postlex is None:
96-
self.tokens = parser.terminals.copy()
97-
rules = parser.rules.copy()
98-
else:
99-
if not hasattr(parser, 'grammar') and parser.options.cache:
100-
raise ConfigurationError('Unanalyzed grammar not available from cached parser, use cache_grammar=True')
98+
if parser.options.postlex and parser.options.postlex.always_accept:
99+
# If postlexer's always_accept is used, we need to recompile the grammar with empty terminals-to-keep
100+
if not hasattr(parser, 'grammar'):
101+
raise ConfigurationError('Source grammar not available from cached parser, use cache_grammar=True'
102+
if parser.options.cache else "Source grammar not available!")
101103
self.tokens, rules, _extra = parser.grammar.compile(parser.options.start, set())
104+
else:
105+
self.tokens = list(parser.terminals)
106+
rules = list(parser.rules)
102107

103108
self.rules_for_root = defaultdict(list)
104109

@@ -109,9 +114,9 @@ def __init__(self, parser):
109114
self.rules = _best_rules_from_group(self.rules)
110115

111116
self.parser = parser
112-
self._parser_cache = {}
117+
self._parser_cache: Dict[str, earley.Parser] = {}
113118

114-
def _build_recons_rules(self, rules):
119+
def _build_recons_rules(self, rules: List[Rule]):
115120
"Convert tree-parsing/construction rules to tree-matching rules"
116121
expand1s = {r.origin for r in rules if r.options.expand1}
117122

@@ -153,7 +158,7 @@ def _build_recons_rules(self, rules):
153158
yield make_recons_rule_to_term(origin, NonTerminal(alias))
154159
yield make_recons_rule_to_term(origin, origin)
155160

156-
def match_tree(self, tree, rulename):
161+
def match_tree(self, tree: Tree, rulename: str) -> Tree:
157162
"""Match the elements of `tree` to the symbols of rule `rulename`.
158163
159164
Parameters:
@@ -167,7 +172,7 @@ def match_tree(self, tree, rulename):
167172
UnexpectedToken: If no match was found.
168173
169174
Note:
170-
It's the callers' responsibility match the tree recursively.
175+
It's the callers' responsibility to match the tree recursively.
171176
"""
172177
if rulename:
173178
# validate
@@ -184,11 +189,11 @@ def match_tree(self, tree, rulename):
184189

185190
# TODO pass callbacks through dict, instead of alias?
186191
callbacks = {rule: rule.alias for rule in rules}
187-
conf = ParserConf(rules, callbacks, [rulename])
192+
conf = ParserConf(rules, callbacks, [rulename]) # type: ignore[arg-type]
188193
parser = earley.Parser(self.parser.lexer_conf, conf, _match, resolve_ambiguity=True)
189194
self._parser_cache[rulename] = parser
190195

191196
# find a full derivation
192-
unreduced_tree = parser.parse(ChildrenLexer(tree.children), rulename)
197+
unreduced_tree: Tree = parser.parse(ChildrenLexer(tree.children), rulename)
193198
assert unreduced_tree.data == rulename
194199
return unreduced_tree

0 commit comments

Comments
 (0)