From 9b22d41e4903119bb2632cb8057c9a8c420961fa Mon Sep 17 00:00:00 2001 From: Rogdham Date: Wed, 20 Feb 2019 10:25:15 +0100 Subject: [PATCH] Change namespace naming and aliasing for imports The `.` character is invalid as a group name in regex, replacing by `__`. The bug arose in `lexer._build_mres`. --- lark/load_grammar.py | 4 +-- tests/grammars/ab.lark | 10 ++++++ tests/test_parser.py | 31 +++++++++++++++++++ tests/test_relative_rule_import.lark | 7 +++++ ...test_relative_rule_import_drop_ignore.lark | 7 +++++ tests/test_relative_rule_import_subrule.lark | 7 +++++ 6 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 tests/grammars/ab.lark create mode 100644 tests/test_relative_rule_import.lark create mode 100644 tests/test_relative_rule_import_drop_ignore.lark create mode 100644 tests/test_relative_rule_import_subrule.lark diff --git a/lark/load_grammar.py b/lark/load_grammar.py index f95d0fa..c8d834e 100644 --- a/lark/load_grammar.py +++ b/lark/load_grammar.py @@ -586,7 +586,7 @@ def import_from_grammar_into_namespace(grammar, namespace, aliases): try: return aliases[name].value except KeyError: - return '%s.%s' % (namespace, name) + return '%s__%s' % (namespace, name) to_import = list(bfs(aliases, rule_dependencies)) for symbol in to_import: @@ -745,7 +745,7 @@ class GrammarLoader: g = import_grammar(grammar_path, base_paths=[base_path]) aliases_dict = dict(zip(names, aliases)) - new_td, new_rd = import_from_grammar_into_namespace(g, '.'.join(dotted_path), aliases_dict) + new_td, new_rd = import_from_grammar_into_namespace(g, '__'.join(dotted_path), aliases_dict) term_defs += new_td rule_defs += new_rd diff --git a/tests/grammars/ab.lark b/tests/grammars/ab.lark new file mode 100644 index 0000000..33a985a --- /dev/null +++ b/tests/grammars/ab.lark @@ -0,0 +1,10 @@ +startab: expr + +expr: A B + | A expr B + +A: "a" +B: "b" + +%import common.WS +%ignore WS diff --git a/tests/test_parser.py b/tests/test_parser.py index c5fabcc..397efc6 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -1025,6 +1025,37 @@ def _make_parser_test(LEXER, PARSER): self.assertEqual(x.children, ['12', 'lions']) + def test_relative_rule_import(self): + l = _Lark_open('test_relative_rule_import.lark', rel_to=__file__) + x = l.parse('xaabby') + self.assertEqual(x.children, [ + 'x', + Tree('expr', ['a', Tree('expr', ['a', 'b']), 'b']), + 'y']) + + + def test_relative_rule_import_drop_ignore(self): + # %ignore rules are dropped on import + l = _Lark_open('test_relative_rule_import_drop_ignore.lark', + rel_to=__file__) + self.assertRaises((ParseError, UnexpectedInput), + l.parse, 'xa abby') + + + def test_relative_rule_import_subrule(self): + l = _Lark_open('test_relative_rule_import_subrule.lark', + rel_to=__file__) + x = l.parse('xaabby') + self.assertEqual(x.children, [ + 'x', + Tree('startab', [ + Tree('grammars__ab__expr', [ + 'a', Tree('grammars__ab__expr', ['a', 'b']), 'b', + ]), + ]), + 'y']) + + def test_multi_import(self): grammar = """ start: NUMBER WORD diff --git a/tests/test_relative_rule_import.lark b/tests/test_relative_rule_import.lark new file mode 100644 index 0000000..e3a33a5 --- /dev/null +++ b/tests/test_relative_rule_import.lark @@ -0,0 +1,7 @@ +start: X expr Y + +X: "x" +Y: "y" + +%import .grammars.ab.expr + diff --git a/tests/test_relative_rule_import_drop_ignore.lark b/tests/test_relative_rule_import_drop_ignore.lark new file mode 100644 index 0000000..e3a33a5 --- /dev/null +++ b/tests/test_relative_rule_import_drop_ignore.lark @@ -0,0 +1,7 @@ +start: X expr Y + +X: "x" +Y: "y" + +%import .grammars.ab.expr + diff --git a/tests/test_relative_rule_import_subrule.lark b/tests/test_relative_rule_import_subrule.lark new file mode 100644 index 0000000..94d7f80 --- /dev/null +++ b/tests/test_relative_rule_import_subrule.lark @@ -0,0 +1,7 @@ +start: X startab Y + +X: "x" +Y: "y" + +%import .grammars.ab.startab +