graph_vals.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import pydotplus.graphviz as pdp
  2. def parse(str_in, alias=None):
  3. """ Creates a call-tree for the supplied value name
  4. """
  5. str_in = "("+str_in+")"
  6. functions = []
  7. ends = {}
  8. nests = {}
  9. names = {}
  10. styles = {}
  11. parens = []
  12. name = ""
  13. name_start = 0
  14. name_end = 0
  15. for i, char in enumerate(str_in):
  16. if char == "(":
  17. nests[name_start] = []
  18. if parens:
  19. nests[parens[-1]].append(name_start)
  20. names[name_start] = name # save function name
  21. styles[name_start] = {"shape": "ellipse"}
  22. name = ""
  23. parens.append(name_start)
  24. elif char == ")":
  25. if name:
  26. ends[name_start] = name_end
  27. names[name_start] = name
  28. styles[name_start] = {"shape": "rectangle"}
  29. nests[parens[-1]].append(name_start)
  30. name = ""
  31. ends[parens.pop()] = i
  32. elif char in ",:":
  33. if name:
  34. ends[name_start] = name_end
  35. names[name_start] = name
  36. if char == ",":
  37. styles[name_start] = {"shape": "rectangle"}
  38. else:
  39. styles[name_start] = {"shape": "invhouse"}
  40. functions.append(name)
  41. nests[parens[-1]].append(name_start)
  42. name = ""
  43. else:
  44. if not name:
  45. name_start = i
  46. name += char
  47. name_end = i
  48. # clean up duplicate sub-trees
  49. text = {}
  50. for start, end in ends.items():
  51. s = str_in[start:end+1]
  52. if s in text:
  53. dup_id = text[s]
  54. names.pop(start)
  55. if start in nests:
  56. nests.pop(start)
  57. for l in nests.values():
  58. for i in range(len(l)):
  59. if l[i] == start:
  60. l[i] = dup_id
  61. else:
  62. text[s] = start
  63. names.pop(0)
  64. nests.pop(0)
  65. g = pdp.Dot()
  66. for id_, name in names.items():
  67. g.add_node(pdp.Node(str(id_), label=name, **styles[id_]))
  68. for group_id, children in nests.items():
  69. for child_id in children:
  70. g.add_edge(pdp.Edge(str(group_id), str(child_id)))
  71. if alias:
  72. g.add_node(pdp.Node(alias, shape="plain", pos="0,0!"))
  73. return g, functions
  74. if __name__ == '__main__':
  75. import re
  76. import sys
  77. aliases = {}
  78. ali_re = re.compile(r"ALIAS::\"([^\"]*)\" referring to \"([^\"]*)\"")
  79. with open(sys.argv[1]) as f:
  80. for line in f.readlines():
  81. res = ali_re.findall(line)
  82. if res:
  83. aliases[res[0][1]] = res[0][0]
  84. continue
  85. for name, alias in aliases.items():
  86. graph, _ = parse(name, alias)
  87. fname = "val_graph_{}.gif".format(alias)
  88. with open(fname, "wb") as f:
  89. try:
  90. f.write(graph.create_gif())
  91. except Exception as e:
  92. print(e)
  93. print(graph.to_string())