This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

110 lines
2.9 KiB

  1. import inspect
  2. from functools import wraps
  3. from . import utils
  4. from .tree import Tree
  5. class Discard(Exception):
  6. pass
  7. class Base:
  8. def _call_userfunc(self, tree):
  9. return getattr(self, tree.data, self.__default__)(tree)
  10. def __default__(self, tree):
  11. return tree
  12. class Transformer(Base):
  13. def _transform_children(self, children):
  14. for c in children:
  15. try:
  16. yield self._transform(c) if isinstance(c, Tree) else c
  17. except Discard:
  18. pass
  19. def _transform(self, tree):
  20. tree = Tree(tree.data, list(self._transform_children(tree.children)))
  21. return self._call_userfunc(tree)
  22. def transform(self, tree):
  23. return self._transform(tree)
  24. def __mul__(self, other):
  25. return TransformerChain(self, other)
  26. class ChildrenTransformer(Transformer):
  27. def _call_userfunc(self, tree):
  28. # Assumes tree is already transformed
  29. try:
  30. f = getattr(self, tree.data)
  31. except AttributeError:
  32. return self.__default__(tree)
  33. else:
  34. return f(tree.children)
  35. class ChildrenInlineTransformer(Transformer):
  36. def _call_userfunc(self, tree):
  37. # Assumes tree is already transformed
  38. try:
  39. f = getattr(self, tree.data)
  40. except AttributeError:
  41. return self.__default__(tree)
  42. else:
  43. return f(*tree.children)
  44. class TransformerChain(object):
  45. def __init__(self, *transformers):
  46. self.transformers = transformers
  47. def transform(self, tree):
  48. for t in self.transformers:
  49. tree = t.transform(tree)
  50. return tree
  51. def __mul__(self, other):
  52. return TransformerChain(*self.transformers + (other,))
  53. class Transformer_InPlace(Transformer):
  54. def _transform(self, tree):
  55. return self._call_userfunc(tree)
  56. def transform(self, tree):
  57. for subtree in tree.iter_subtrees():
  58. subtree.children = list(self._transform_children(subtree.children))
  59. return self._transform(tree)
  60. class Visitor(Base):
  61. def visit(self, tree):
  62. for subtree in tree.iter_subtrees():
  63. self._call_userfunc(subtree)
  64. return tree
  65. class Transformer_InPlaceRecursive(Transformer):
  66. def _transform(self, tree):
  67. tree.children = list(self._transform_children(tree.children))
  68. return self._call_userfunc(tree)
  69. class Visitor_Recursive(Base):
  70. def visit(self, tree):
  71. for child in tree.children:
  72. if isinstance(child, Tree):
  73. self.visit(child)
  74. f = getattr(self, tree.data, self.__default__)
  75. f(tree)
  76. return tree
  77. def inline_args(obj):
  78. if inspect.isclass(obj) and issubclass(obj, ChildrenTransformer):
  79. class _NewTransformer(ChildrenInlineTransformer, obj):
  80. pass
  81. return _NewTransformer
  82. else:
  83. return utils.inline_args(obj)