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.

163 lines
4.3 KiB

  1. try:
  2. from future_builtins import filter
  3. except ImportError:
  4. pass
  5. from copy import deepcopy
  6. ###{standalone
  7. class Meta:
  8. pass
  9. class Tree(object):
  10. def __init__(self, data, children, meta=None):
  11. self.data = data
  12. self.children = children
  13. self._meta = meta
  14. @property
  15. def meta(self):
  16. if self._meta is None:
  17. self._meta = Meta()
  18. return self._meta
  19. def __repr__(self):
  20. return 'Tree(%s, %s)' % (self.data, self.children)
  21. def _pretty_label(self):
  22. return self.data
  23. def _pretty(self, level, indent_str):
  24. if len(self.children) == 1 and not isinstance(self.children[0], Tree):
  25. return [ indent_str*level, self._pretty_label(), '\t', '%s' % (self.children[0],), '\n']
  26. l = [ indent_str*level, self._pretty_label(), '\n' ]
  27. for n in self.children:
  28. if isinstance(n, Tree):
  29. l += n._pretty(level+1, indent_str)
  30. else:
  31. l += [ indent_str*(level+1), '%s' % (n,), '\n' ]
  32. return l
  33. def pretty(self, indent_str=' '):
  34. return ''.join(self._pretty(0, indent_str))
  35. def __eq__(self, other):
  36. try:
  37. return self.data == other.data and self.children == other.children
  38. except AttributeError:
  39. return False
  40. def __ne__(self, other):
  41. return not (self == other)
  42. def __hash__(self):
  43. return hash((self.data, tuple(self.children)))
  44. ###}
  45. def expand_kids_by_index(self, *indices):
  46. "Expand (inline) children at the given indices"
  47. for i in sorted(indices, reverse=True): # reverse so that changing tail won't affect indices
  48. kid = self.children[i]
  49. self.children[i:i+1] = kid.children
  50. def find_pred(self, pred):
  51. "Find all nodes where pred(tree) == True"
  52. return filter(pred, self.iter_subtrees())
  53. def find_data(self, data):
  54. "Find all nodes where tree.data == data"
  55. return self.find_pred(lambda t: t.data == data)
  56. def scan_values(self, pred):
  57. for c in self.children:
  58. if isinstance(c, Tree):
  59. for t in c.scan_values(pred):
  60. yield t
  61. else:
  62. if pred(c):
  63. yield c
  64. def iter_subtrees(self):
  65. # TODO: Re-write as a more efficient version
  66. visited = set()
  67. q = [self]
  68. l = []
  69. while q:
  70. subtree = q.pop()
  71. l.append( subtree )
  72. if id(subtree) in visited:
  73. continue # already been here from another branch
  74. visited.add(id(subtree))
  75. q += [c for c in subtree.children if isinstance(c, Tree)]
  76. seen = set()
  77. for x in reversed(l):
  78. if id(x) not in seen:
  79. yield x
  80. seen.add(id(x))
  81. def __deepcopy__(self, memo):
  82. return type(self)(self.data, deepcopy(self.children, memo))
  83. def copy(self):
  84. return type(self)(self.data, self.children)
  85. def set(self, data, children):
  86. self.data = data
  87. self.children = children
  88. # XXX Deprecated! Here for backwards compatibility <0.6.0
  89. @property
  90. def line(self):
  91. return self.meta.line
  92. @property
  93. def column(self):
  94. return self.meta.column
  95. @property
  96. def end_line(self):
  97. return self.meta.end_line
  98. @property
  99. def end_column(self):
  100. return self.meta.end_column
  101. class SlottedTree(Tree):
  102. __slots__ = 'data', 'children', 'rule', '_meta'
  103. def pydot__tree_to_png(tree, filename):
  104. "Creates a colorful image that represents the tree (data+children, without meta)"
  105. import pydot
  106. graph = pydot.Dot(graph_type='digraph', rankdir="LR")
  107. i = [0]
  108. def new_leaf(leaf):
  109. node = pydot.Node(i[0], label=repr(leaf))
  110. i[0] += 1
  111. graph.add_node(node)
  112. return node
  113. def _to_pydot(subtree):
  114. color = hash(subtree.data) & 0xffffff
  115. color |= 0x808080
  116. subnodes = [_to_pydot(child) if isinstance(child, Tree) else new_leaf(child)
  117. for child in subtree.children]
  118. node = pydot.Node(i[0], style="filled", fillcolor="#%x"%color, label=subtree.data)
  119. i[0] += 1
  120. graph.add_node(node)
  121. for subnode in subnodes:
  122. graph.add_edge(pydot.Edge(node, subnode))
  123. return node
  124. _to_pydot(tree)
  125. graph.write_png(filename)