|
|
@@ -19,17 +19,22 @@ class Transformer: |
|
|
|
Can be used to implement map or reduce. |
|
|
|
""" |
|
|
|
|
|
|
|
def _call_userfunc(self, data, children, meta): |
|
|
|
def _call_userfunc(self, tree, new_children=None): |
|
|
|
# Assumes tree is already transformed |
|
|
|
children = new_children if new_children is not None else tree.children |
|
|
|
try: |
|
|
|
f = getattr(self, data) |
|
|
|
f = getattr(self, tree.data) |
|
|
|
except AttributeError: |
|
|
|
return self.__default__(data, children, meta) |
|
|
|
return self.__default__(tree.data, children, tree.meta) |
|
|
|
else: |
|
|
|
if getattr(f, 'meta', False): |
|
|
|
return f(children, meta) |
|
|
|
return f(children, tree.meta) |
|
|
|
elif getattr(f, 'inline', False): |
|
|
|
return f(*children) |
|
|
|
elif getattr(f, 'whole_tree', False): |
|
|
|
if new_children is not None: |
|
|
|
raise NotImplementedError("Doesn't work with the base Transformer class") |
|
|
|
return f(tree) |
|
|
|
else: |
|
|
|
return f(children) |
|
|
|
|
|
|
@@ -42,7 +47,7 @@ class Transformer: |
|
|
|
|
|
|
|
def _transform_tree(self, tree): |
|
|
|
children = list(self._transform_children(tree.children)) |
|
|
|
return self._call_userfunc(tree.data, children, tree.meta) |
|
|
|
return self._call_userfunc(tree, children) |
|
|
|
|
|
|
|
def transform(self, tree): |
|
|
|
return self._transform_tree(tree) |
|
|
@@ -68,12 +73,13 @@ class Transformer: |
|
|
|
|
|
|
|
|
|
|
|
class InlineTransformer(Transformer): # XXX Deprecated |
|
|
|
def _call_userfunc(self, data, children, meta): |
|
|
|
def _call_userfunc(self, tree, new_children=None): |
|
|
|
# Assumes tree is already transformed |
|
|
|
children = new_children if new_children is not None else tree.children |
|
|
|
try: |
|
|
|
f = getattr(self, data) |
|
|
|
f = getattr(self, tree.data) |
|
|
|
except AttributeError: |
|
|
|
return self.__default__(data, children, meta) |
|
|
|
return self.__default__(tree.data, children, tree.meta) |
|
|
|
else: |
|
|
|
return f(*children) |
|
|
|
|
|
|
@@ -94,7 +100,7 @@ class TransformerChain(object): |
|
|
|
class Transformer_InPlace(Transformer): |
|
|
|
"Non-recursive. Changes the tree in-place instead of returning new instances" |
|
|
|
def _transform_tree(self, tree): # Cancel recursion |
|
|
|
return self._call_userfunc(tree.data, tree.children, tree.meta) |
|
|
|
return self._call_userfunc(tree) |
|
|
|
|
|
|
|
def transform(self, tree): |
|
|
|
for subtree in tree.iter_subtrees(): |
|
|
@@ -107,7 +113,7 @@ class Transformer_InPlaceRecursive(Transformer): |
|
|
|
"Recursive. Changes the tree in-place instead of returning new instances" |
|
|
|
def _transform_tree(self, tree): |
|
|
|
tree.children = list(self._transform_children(tree.children)) |
|
|
|
return self._call_userfunc(tree.data, tree.children, tree.meta) |
|
|
|
return self._call_userfunc(tree) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -218,8 +224,8 @@ def inline_args(obj): # XXX Deprecated |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _visitor_args_func_dec(func, inline=False, meta=False): |
|
|
|
assert not (inline and meta) |
|
|
|
def _visitor_args_func_dec(func, inline=False, meta=False, whole_tree=False): |
|
|
|
assert [whole_tree, meta, inline].count(True) <= 1 |
|
|
|
def create_decorator(_f, with_self): |
|
|
|
if with_self: |
|
|
|
def f(self, *args, **kwargs): |
|
|
@@ -232,14 +238,15 @@ def _visitor_args_func_dec(func, inline=False, meta=False): |
|
|
|
f = smart_decorator(func, create_decorator) |
|
|
|
f.inline = inline |
|
|
|
f.meta = meta |
|
|
|
f.whole_tree = whole_tree |
|
|
|
return f |
|
|
|
|
|
|
|
def v_args(inline=False, meta=False): |
|
|
|
def v_args(inline=False, meta=False, tree=False): |
|
|
|
"A convenience decorator factory, for modifying the behavior of user-supplied visitor methods" |
|
|
|
if inline and meta: |
|
|
|
raise ValueError("Visitor functions can either accept meta, or be inlined. Not both.") |
|
|
|
if [tree, meta, inline].count(True) > 1: |
|
|
|
raise ValueError("Visitor functions can either accept tree, or meta, or be inlined. These cannot be combined.") |
|
|
|
def _visitor_args_dec(obj): |
|
|
|
return _apply_decorator(obj, _visitor_args_func_dec, inline=inline, meta=meta) |
|
|
|
return _apply_decorator(obj, _visitor_args_func_dec, inline=inline, meta=meta, whole_tree=tree) |
|
|
|
return _visitor_args_dec |
|
|
|
|
|
|
|
|