@@ -407,7 +407,7 @@ class TokenTreeToPattern(ChildrenTransformer): | |||||
def value(self, v): | def value(self, v): | ||||
return v[0] | return v[0] | ||||
class PrepareSymbols(Transformer): | |||||
class PrepareSymbols(ChildrenTransformer): | |||||
def value(self, v): | def value(self, v): | ||||
v ,= v | v ,= v | ||||
if isinstance(v, Tree): | if isinstance(v, Tree): | ||||
@@ -532,7 +532,8 @@ def options_from_rule(name, *x): | |||||
def symbols_from_strcase(expansion): | def symbols_from_strcase(expansion): | ||||
return [Terminal(x, filter_out=x.startswith('_')) if is_terminal(x) else NonTerminal(x) for x in expansion] | return [Terminal(x, filter_out=x.startswith('_')) if is_terminal(x) else NonTerminal(x) for x in expansion] | ||||
class PrepareGrammar(InlineTransformer): | |||||
@inline_args | |||||
class PrepareGrammar(ChildrenTransformer): | |||||
def terminal(self, name): | def terminal(self, name): | ||||
return name | return name | ||||
def nonterminal(self, name): | def nonterminal(self, name): | ||||
@@ -78,6 +78,8 @@ class Transformer_InPlace(Transformer): | |||||
return self._transform(tree) | return self._transform(tree) | ||||
class Visitor(Base): | class Visitor(Base): | ||||
"Bottom-up visitor" | |||||
def visit(self, tree): | def visit(self, tree): | ||||
for subtree in tree.iter_subtrees(): | for subtree in tree.iter_subtrees(): | ||||
self._call_userfunc(subtree) | self._call_userfunc(subtree) | ||||
@@ -99,6 +101,31 @@ class Visitor_Recursive(Base): | |||||
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): | |||||
"Top-down visitor" | |||||
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): | |||||
return self.visit_children(tree) | |||||
def inline_args(obj): | def inline_args(obj): | ||||
if inspect.isclass(obj) and issubclass(obj, ChildrenTransformer): | if inspect.isclass(obj) and issubclass(obj, ChildrenTransformer): | ||||
class _NewTransformer(ChildrenInlineTransformer, obj): | class _NewTransformer(ChildrenInlineTransformer, obj): | ||||
@@ -5,7 +5,8 @@ from unittest import TestCase | |||||
import copy | import copy | ||||
import pickle | import pickle | ||||
from lark.tree import Tree, Interpreter, visit_children_decor | |||||
from lark.tree import Tree | |||||
from lark.transformers import Interpreter, visit_children_decor | |||||
class TestTrees(TestCase): | class TestTrees(TestCase): | ||||