Browse Source

Correct behaviour of aliases for templates (attempt 2)

tags/gm/2021-09-23T00Z/github.com--lark-parser-lark/0.8.6
MegaIng1 4 years ago
parent
commit
20a2f690ca
4 changed files with 42 additions and 17 deletions
  1. +5
    -3
      lark/grammar.py
  2. +2
    -12
      lark/load_grammar.py
  3. +3
    -2
      lark/parse_tree_builder.py
  4. +32
    -0
      tests/test_parser.py

+ 5
- 3
lark/grammar.py View File

@@ -49,19 +49,21 @@ class NonTerminal(Symbol):


class RuleOptions(Serialize):
__serialize_fields__ = 'keep_all_tokens', 'expand1', 'priority', 'empty_indices'
__serialize_fields__ = 'keep_all_tokens', 'expand1', 'priority', 'template_source', 'empty_indices'

def __init__(self, keep_all_tokens=False, expand1=False, priority=None, empty_indices=()):
def __init__(self, keep_all_tokens=False, expand1=False, priority=None, template_source=None, empty_indices=()):
self.keep_all_tokens = keep_all_tokens
self.expand1 = expand1
self.priority = priority
self.template_source = template_source
self.empty_indices = empty_indices

def __repr__(self):
return 'RuleOptions(%r, %r, %r)' % (
return 'RuleOptions(%r, %r, %r, %r)' % (
self.keep_all_tokens,
self.expand1,
self.priority,
self.template_source
)




+ 2
- 12
lark/load_grammar.py View File

@@ -383,17 +383,6 @@ class ApplyTemplates(Transformer_InPlace):
result_tree = deepcopy(tree)
self.replacer.names = dict(zip(params, args))
self.replacer.transform(result_tree)
if name[0] != '_':
if result_tree.data == 'expansions':
t = result_tree
while len(t.children) == 2:
if t.children[-1].data != 'alias':
t.children[-1] = ST('alias', [t.children[-1], name])
t = t.children[0]
if t.children[-1].data != 'alias':
t.children[-1] = ST('alias', [t.children[-1], name])
elif result_tree.data != 'alias':
result_tree = ST('alias', [result_tree, name])
self.rule_defs.append((result_name, [], result_tree, deepcopy(options)))
return NonTerminal(result_name)

@@ -736,7 +725,8 @@ def options_from_rule(name, params, *x):
expand1 = name.startswith('?')
name = name.lstrip('?')

return name, params, expansions, RuleOptions(keep_all_tokens, expand1, priority=priority)
return name, params, expansions, RuleOptions(keep_all_tokens, expand1, priority=priority,
template_source=(name if params else None))


def symbols_from_strcase(expansion):


+ 3
- 2
lark/parse_tree_builder.py View File

@@ -227,9 +227,10 @@ class ParseTreeBuilder:
options = rule.options
keep_all_tokens = self.always_keep_all_tokens or options.keep_all_tokens
expand_single_child = options.expand1
from_template = options.template_source is not None

wrapper_chain = list(filter(None, [
(expand_single_child and not rule.alias) and ExpandSingleChild,
(expand_single_child and not (rule.alias and not from_template)) and ExpandSingleChild,
maybe_create_child_filter(rule.expansion, keep_all_tokens, self.ambiguous, options.empty_indices if self.maybe_placeholders else None),
self.propagate_positions and PropagatePositions,
self.ambiguous and maybe_create_ambiguous_expander(self.tree_class, rule.expansion, keep_all_tokens),
@@ -243,7 +244,7 @@ class ParseTreeBuilder:

for rule, wrapper_chain in self.rule_builders:

user_callback_name = rule.alias or rule.origin.name
user_callback_name = rule.alias or rule.options.template_source or rule.origin.name
try:
f = getattr(transformer, user_callback_name)
# XXX InlineTransformer is deprecated!


+ 32
- 0
tests/test_parser.py View File

@@ -863,6 +863,38 @@ def _make_parser_test(LEXER, PARSER):
x = g.parse("[1]")
self.assertSequenceEqual(x.children, [Tree('sep', ['1'])])

def test_templates_alias(self):
g = _Lark(r"""
start: expr{"C"}
expr{t}: "A" t
| "B" t -> b
""")
x = g.parse("AC")
self.assertSequenceEqual(x.children, [Tree('expr', [])])
x = g.parse("BC")
self.assertSequenceEqual(x.children, [Tree('b', [])])
def test_templates_modifiers(self):
g = _Lark(r"""
start: expr{"B"}
!expr{t}: "A" t
""")
x = g.parse("AB")
self.assertSequenceEqual(x.children, [Tree('expr', ["A", "B"])])
g = _Lark(r"""
start: _expr{"B"}
!_expr{t}: "A" t
""")
x = g.parse("AB")
self.assertSequenceEqual(x.children, ["A", "B"])
g = _Lark(r"""
start: expr{b}
b: "B"
?expr{t}: "A" t
""")
x = g.parse("AB")
self.assertSequenceEqual(x.children, [Tree('b',[])])

def test_g_regex_flags(self):
g = _Lark("""
start: "a" /b+/ C


Loading…
Cancel
Save