From efc1c82221b511d9b08d485bbe8741a11edfb0e8 Mon Sep 17 00:00:00 2001 From: Erez Sh Date: Tue, 17 Nov 2020 23:57:51 +0200 Subject: [PATCH 1/2] Added support for returning Inline in transformers (Issue #763) --- lark/__init__.py | 2 +- lark/visitors.py | 20 ++++++++++++++++---- tests/test_trees.py | 20 +++++++++++++++++++- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/lark/__init__.py b/lark/__init__.py index 814fe66a..855c65dd 100644 --- a/lark/__init__.py +++ b/lark/__init__.py @@ -1,6 +1,6 @@ from .utils import logger from .tree import Tree -from .visitors import Transformer, Visitor, v_args, Discard, Transformer_NonRecursive +from .visitors import Transformer, Visitor, v_args, Discard, Inline, Transformer_NonRecursive from .visitors import InlineTransformer, inline_args # XXX Deprecated from .exceptions import (ParseError, LexError, GrammarError, UnexpectedToken, UnexpectedInput, UnexpectedCharacters, LarkError) diff --git a/lark/visitors.py b/lark/visitors.py index 7e3bae4b..14b89f22 100644 --- a/lark/visitors.py +++ b/lark/visitors.py @@ -15,9 +15,16 @@ class Discard(Exception): """ pass -# Transformers +class Inline: + """When returning an Inline instance in a transformer callback, + the node is inlined, and replaced by its children. + """ + def __init__(self, *items): + self.items = items +# Transformers + class _Decoratable: "Provides support for decorating methods with @v_args" @@ -113,11 +120,16 @@ def _transform_children(self, children): for c in children: try: if isinstance(c, Tree): - yield self._transform_tree(c) + res = self._transform_tree(c) elif self.__visit_tokens__ and isinstance(c, Token): - yield self._call_userfunc_token(c) + res = self._call_userfunc_token(c) + else: + res = c + if type(res) is Inline: + for i in res.items: + yield i else: - yield c + yield res except Discard: pass diff --git a/tests/test_trees.py b/tests/test_trees.py index 905ad5ab..e91e10d1 100644 --- a/tests/test_trees.py +++ b/tests/test_trees.py @@ -8,7 +8,7 @@ from lark.tree import Tree from lark.lexer import Token -from lark.visitors import Visitor, Visitor_Recursive, Transformer, Interpreter, visit_children_decor, v_args, Discard +from lark.visitors import Visitor, Visitor_Recursive, Transformer, Interpreter, visit_children_decor, v_args, Discard, Inline class TestTrees(TestCase): @@ -233,6 +233,24 @@ def b(cls, args): x = MyTransformer().transform( t ) self.assertEqual(x, t2) + def test_inline(self): + class MyTransformer(Transformer): + def b(self, children): + return 'b' + + def a(self, children): + return Inline('c', 'd') + + t = Tree('root', [ + Tree('b', []), + Tree('a', []), + Tree('b', []), + ]) + t2 = Tree('root', ['b', 'c', 'd', 'b']) + + x = MyTransformer().transform( t ) + self.assertEqual(x, t2) + if __name__ == '__main__': unittest.main() From 1b628ab9ea49f0115de2705f01795553a3e07d5a Mon Sep 17 00:00:00 2001 From: Erez Sh Date: Wed, 18 Nov 2020 00:39:26 +0200 Subject: [PATCH 2/2] Fix for Python2 --- lark/visitors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lark/visitors.py b/lark/visitors.py index 14b89f22..62aeb2ed 100644 --- a/lark/visitors.py +++ b/lark/visitors.py @@ -15,7 +15,7 @@ class Discard(Exception): """ pass -class Inline: +class Inline(object): """When returning an Inline instance in a transformer callback, the node is inlined, and replaced by its children. """