It emulates antlr's visitor behavior for a dynamic evaluation order of subtreestags/gm/2021-09-23T00Z/github.com--lark-parser-lark/0.6.0
@@ -174,6 +174,30 @@ class Visitor_NoRecurse(Visitor): | |||||
return tree | return tree | ||||
from functools import wraps | |||||
def visit_children_decor(func): | |||||
@wraps(func) | |||||
def inner(cls, tree): | |||||
values = cls.visit_children(tree) | |||||
return func(cls, values) | |||||
return inner | |||||
class Interpreter(object): | |||||
def visit(self, tree): | |||||
return getattr(self, tree.data)(tree) | |||||
def visit_children(self, tree): | |||||
return [self.visit(child) if isinstance(child, Tree) else child | |||||
for child in tree.children] | |||||
def __getattr__(self, name): | |||||
return self.__default__ | |||||
def __default__(self, tree): | |||||
self.visit_children(tree) | |||||
class Transformer_NoRecurse(Transformer): | class Transformer_NoRecurse(Transformer): | ||||
def transform(self, tree): | def transform(self, tree): | ||||
subtrees = list(tree.iter_subtrees()) | subtrees = list(tree.iter_subtrees()) | ||||
@@ -5,7 +5,7 @@ from unittest import TestCase | |||||
import copy | import copy | ||||
import pickle | import pickle | ||||
from lark.tree import Tree | |||||
from lark.tree import Tree, Interpreter, visit_children_decor | |||||
class TestTrees(TestCase): | class TestTrees(TestCase): | ||||
@@ -21,6 +21,37 @@ class TestTrees(TestCase): | |||||
assert pickle.loads(data) == s | assert pickle.loads(data) == s | ||||
def test_interp(self): | |||||
t = Tree('a', [Tree('b', []), Tree('c', []), 'd']) | |||||
class Interp1(Interpreter): | |||||
def a(self, tree): | |||||
return self.visit_children(tree) + ['e'] | |||||
def b(self, tree): | |||||
return 'B' | |||||
def c(self, tree): | |||||
return 'C' | |||||
self.assertEqual(Interp1().visit(t), list('BCde')) | |||||
class Interp2(Interpreter): | |||||
@visit_children_decor | |||||
def a(self, values): | |||||
return values + ['e'] | |||||
def b(self, tree): | |||||
return 'B' | |||||
def c(self, tree): | |||||
return 'C' | |||||
self.assertEqual(Interp2().visit(t), list('BCde')) | |||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
unittest.main() | unittest.main() | ||||