Browse Source

Added test for template imports and implemented them

tags/gm/2021-09-23T00Z/github.com--lark-parser-lark/0.8.6
MegaIng1 4 years ago
parent
commit
8bf5da697a
4 changed files with 36 additions and 15 deletions
  1. +24
    -15
      lark/load_grammar.py
  2. +1
    -0
      tests/grammars/templates.lark
  3. +7
    -0
      tests/test_parser.py
  4. +4
    -0
      tests/test_templates_import.lark

+ 24
- 15
lark/load_grammar.py View File

@@ -525,8 +525,6 @@ class Grammar:
# ================= # =================
# Compile Rules # Compile Rules
# ================= # =================
# TODO: add templates


# 1. Pre-process terminals # 1. Pre-process terminals
transformer = PrepareLiterals() * PrepareSymbols() * PrepareAnonTerminals(terminals) # Adds to terminals transformer = PrepareLiterals() * PrepareSymbols() * PrepareAnonTerminals(terminals) # Adds to terminals
@@ -640,7 +638,7 @@ def import_from_grammar_into_namespace(grammar, namespace, aliases):


imported_terms = dict(grammar.term_defs) imported_terms = dict(grammar.term_defs)
imported_rules = {n:(n,deepcopy(t),o) for n,t,o in grammar.rule_defs} imported_rules = {n:(n,deepcopy(t),o) for n,t,o in grammar.rule_defs}
imported_temps = {n:(n,deepcopy(t),o) for n,t,o in grammar.temp_defs}
imported_temps = {n:(n,p,deepcopy(t),o) for n,p,t,o in grammar.temp_defs}


term_defs = [] term_defs = []
rule_defs = [] rule_defs = []
@@ -649,12 +647,13 @@ def import_from_grammar_into_namespace(grammar, namespace, aliases):
def rule_dependencies(symbol): def rule_dependencies(symbol):
if symbol.type != 'RULE': if symbol.type != 'RULE':
return [] return []
try:
_, tree, _ = imported_rules[symbol]
except KeyError:
if symbol in imported_rules:
return _find_used_symbols(imported_rules[symbol][1])
elif symbol in imported_temps:
return _find_used_symbols(imported_temps[symbol][2]) - set(imported_temps[symbol][1])
else:
raise GrammarError("Missing symbol '%s' in grammar %s" % (symbol, namespace)) raise GrammarError("Missing symbol '%s' in grammar %s" % (symbol, namespace))


return _find_used_symbols(tree)




def get_namespace_name(name): def get_namespace_name(name):
@@ -671,14 +670,24 @@ def import_from_grammar_into_namespace(grammar, namespace, aliases):
term_defs.append([get_namespace_name(symbol), imported_terms[symbol]]) term_defs.append([get_namespace_name(symbol), imported_terms[symbol]])
else: else:
assert symbol.type == 'RULE' assert symbol.type == 'RULE'
rule = imported_rules[symbol]
for t in rule[1].iter_subtrees():
for i, c in enumerate(t.children):
if isinstance(c, Token) and c.type in ('RULE', 'TERMINAL'):
t.children[i] = Token(c.type, get_namespace_name(c))
rule_defs.append((get_namespace_name(symbol), rule[1], rule[2]))

return term_defs, rule_defs
if symbol in imported_rules:
rule = imported_rules[symbol]
for t in rule[1].iter_subtrees():
for i, c in enumerate(t.children):
if isinstance(c, Token) and c.type in ('RULE', 'TERMINAL'):
t.children[i] = Token(c.type, get_namespace_name(c))
rule_defs.append((get_namespace_name(symbol), rule[1], rule[2]))
else:
temp = imported_temps[symbol]
for t in temp[2].iter_subtrees():
for i, c in enumerate(t.children):
if isinstance(c, Token) and c.type in ('RULE', 'TERMINAL'):
t.children[i] = Token(c.type, get_namespace_name(c))
params = [('%s__%s' if p[0]!='_' else '_%s__%s' ) % (namespace, p) for p in temp[1]]
temp_defs.append((get_namespace_name(symbol), params, temp[2], temp[3]))


return term_defs, rule_defs, temp_defs








+ 1
- 0
tests/grammars/templates.lark View File

@@ -0,0 +1 @@
sep{item, delim}: item (delim item)*

+ 7
- 0
tests/test_parser.py View File

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


def test_templates_import(self):
g = _Lark_open("test_templates_import.lark", rel_to=__file__)
x = g.parse("[1, 2, 3, 4]")
self.assertSequenceEqual(x.children,['1', '2', '3', '4'])
x = g.parse("[1]")
self.assertSequenceEqual(x.children,['1'])

def test_token_collision_WS(self): def test_token_collision_WS(self):
g = _Lark(r"""start: "Hello" NAME g = _Lark(r"""start: "Hello" NAME
NAME: /\w/+ NAME: /\w/+


+ 4
- 0
tests/test_templates_import.lark View File

@@ -0,0 +1,4 @@
start: "[" sep{NUMBER, ","} "]"
NUMBER: /\d+/
%ignore " "
%import .grammars.templates.sep

Loading…
Cancel
Save