This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 

260 líneas
6.6 KiB

  1. try:
  2. from future_builtins import filter
  3. except ImportError:
  4. pass
  5. from copy import deepcopy
  6. from .utils import inline_args
  7. ###{standalone
  8. class Tree(object):
  9. def __init__(self, data, children):
  10. self.data = data
  11. self.children = children
  12. def __repr__(self):
  13. return 'Tree(%s, %s)' % (self.data, self.children)
  14. def _pretty_label(self):
  15. return self.data
  16. def _pretty(self, level, indent_str):
  17. if len(self.children) == 1 and not isinstance(self.children[0], Tree):
  18. return [ indent_str*level, self._pretty_label(), '\t', '%s' % (self.children[0],), '\n']
  19. l = [ indent_str*level, self._pretty_label(), '\n' ]
  20. for n in self.children:
  21. if isinstance(n, Tree):
  22. l += n._pretty(level+1, indent_str)
  23. else:
  24. l += [ indent_str*(level+1), '%s' % (n,), '\n' ]
  25. return l
  26. def pretty(self, indent_str=' '):
  27. return ''.join(self._pretty(0, indent_str))
  28. ###}
  29. def expand_kids_by_index(self, *indices):
  30. for i in sorted(indices, reverse=True): # reverse so that changing tail won't affect indices
  31. kid = self.children[i]
  32. self.children[i:i+1] = kid.children
  33. def __eq__(self, other):
  34. try:
  35. return self.data == other.data and self.children == other.children
  36. except AttributeError:
  37. return False
  38. def __ne__(self, other):
  39. return not (self == other)
  40. def __hash__(self):
  41. return hash((self.data, tuple(self.children)))
  42. def find_pred(self, pred):
  43. return filter(pred, self.iter_subtrees())
  44. def find_data(self, data):
  45. return self.find_pred(lambda t: t.data == data)
  46. def scan_values(self, pred):
  47. for c in self.children:
  48. if isinstance(c, Tree):
  49. for t in c.scan_values(pred):
  50. yield t
  51. else:
  52. if pred(c):
  53. yield c
  54. def iter_subtrees(self):
  55. # TODO: Re-write as a more efficient version
  56. visited = set()
  57. q = [self]
  58. l = []
  59. while q:
  60. subtree = q.pop()
  61. l.append( subtree )
  62. if id(subtree) in visited:
  63. continue # already been here from another branch
  64. visited.add(id(subtree))
  65. q += [c for c in subtree.children if isinstance(c, Tree)]
  66. seen = set()
  67. for x in reversed(l):
  68. if id(x) not in seen:
  69. yield x
  70. seen.add(id(x))
  71. def __deepcopy__(self, memo):
  72. return type(self)(self.data, deepcopy(self.children, memo))
  73. def copy(self):
  74. return type(self)(self.data, self.children)
  75. def set(self, data, children):
  76. self.data = data
  77. self.children = children
  78. class SlottedTree(Tree):
  79. __slots__ = 'data', 'children', 'rule'
  80. ###{standalone
  81. class Transformer(object):
  82. def _get_func(self, name):
  83. return getattr(self, name)
  84. def transform(self, tree):
  85. items = []
  86. for c in tree.children:
  87. try:
  88. items.append(self.transform(c) if isinstance(c, Tree) else c)
  89. except Discard:
  90. pass
  91. try:
  92. f = self._get_func(tree.data)
  93. except AttributeError:
  94. return self.__default__(tree.data, items)
  95. else:
  96. return f(items)
  97. def __default__(self, data, children):
  98. return Tree(data, children)
  99. def __mul__(self, other):
  100. return TransformerChain(self, other)
  101. class Discard(Exception):
  102. pass
  103. class TransformerChain(object):
  104. def __init__(self, *transformers):
  105. self.transformers = transformers
  106. def transform(self, tree):
  107. for t in self.transformers:
  108. tree = t.transform(tree)
  109. return tree
  110. def __mul__(self, other):
  111. return TransformerChain(*self.transformers + (other,))
  112. class InlineTransformer(Transformer):
  113. def _get_func(self, name): # use super()._get_func
  114. return inline_args(getattr(self, name)).__get__(self)
  115. class Visitor(object):
  116. def visit(self, tree):
  117. for child in tree.children:
  118. if isinstance(child, Tree):
  119. self.visit(child)
  120. f = getattr(self, tree.data, self.__default__)
  121. f(tree)
  122. return tree
  123. def __default__(self, tree):
  124. pass
  125. class Visitor_NoRecurse(Visitor):
  126. def visit(self, tree):
  127. subtrees = list(tree.iter_subtrees())
  128. for subtree in (subtrees):
  129. getattr(self, subtree.data, self.__default__)(subtree)
  130. return tree
  131. from functools import wraps
  132. def visit_children_decor(func):
  133. @wraps(func)
  134. def inner(cls, tree):
  135. values = cls.visit_children(tree)
  136. return func(cls, values)
  137. return inner
  138. class Interpreter(object):
  139. def visit(self, tree):
  140. return getattr(self, tree.data)(tree)
  141. def visit_children(self, tree):
  142. return [self.visit(child) if isinstance(child, Tree) else child
  143. for child in tree.children]
  144. def __getattr__(self, name):
  145. return self.__default__
  146. def __default__(self, tree):
  147. return self.visit_children(tree)
  148. class Transformer_NoRecurse(Transformer):
  149. def transform(self, tree):
  150. subtrees = list(tree.iter_subtrees())
  151. def _t(t):
  152. # Assumes t is already transformed
  153. try:
  154. f = self._get_func(t.data)
  155. except AttributeError:
  156. return self.__default__(t)
  157. else:
  158. return f(t)
  159. for subtree in subtrees:
  160. children = []
  161. for c in subtree.children:
  162. try:
  163. children.append(_t(c) if isinstance(c, Tree) else c)
  164. except Discard:
  165. pass
  166. subtree.children = children
  167. return _t(tree)
  168. def __default__(self, t):
  169. return t
  170. ###}
  171. def pydot__tree_to_png(tree, filename):
  172. import pydot
  173. graph = pydot.Dot(graph_type='digraph', rankdir="LR")
  174. i = [0]
  175. def new_leaf(leaf):
  176. node = pydot.Node(i[0], label=repr(leaf))
  177. i[0] += 1
  178. graph.add_node(node)
  179. return node
  180. def _to_pydot(subtree):
  181. color = hash(subtree.data) & 0xffffff
  182. color |= 0x808080
  183. subnodes = [_to_pydot(child) if isinstance(child, Tree) else new_leaf(child)
  184. for child in subtree.children]
  185. node = pydot.Node(i[0], style="filled", fillcolor="#%x"%color, label=subtree.data)
  186. i[0] += 1
  187. graph.add_node(node)
  188. for subnode in subnodes:
  189. graph.add_edge(pydot.Edge(node, subnode))
  190. return node
  191. _to_pydot(tree)
  192. graph.write_png(filename)