postproc.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import json
  2. class Counter(object):
  3. def __init__(self):
  4. self.ctr = 0
  5. def inc(self):
  6. self.ctr += 1
  7. def get(self):
  8. return self.ctr
  9. def postproc(input):
  10. lines = input.split('\n')
  11. graph = dict()
  12. kinds = dict()
  13. # read the graph
  14. for l in lines:
  15. if not l:
  16. continue
  17. if l[0] == "N":
  18. # N [A-z_0-9]+
  19. rest = l[2:]
  20. name = rest
  21. graph[name] = []
  22. elif l[0] == "V":
  23. # V [A-z_0-9]+\(.*?\)
  24. rest = l[2:]
  25. b = rest.find('(')
  26. name = rest[:b]
  27. kind = rest[b+1:-1]
  28. kinds[name] = kind
  29. graph[name] = []
  30. elif l[0] == "D":
  31. # D [A-z_0-9]+,".*?",[A-z_0-9]+
  32. rest = l[2:]
  33. c1 = rest.find(',')
  34. c2 = rest.find(',', c1+1)
  35. origin = rest[:c1]
  36. label = rest[c1+1:c2]
  37. target = rest[c2+1:]
  38. graph[origin].append((label, target))
  39. # order edges by label
  40. for n, edges in graph.iteritems():
  41. edges.sort(key=lambda x:x[0])
  42. renames = dict()
  43. new_graph = dict()
  44. new_kinds = dict()
  45. visited = dict()
  46. free_id = Counter()
  47. def dfs(name):
  48. if visited.get(name, False) == True:
  49. return
  50. new_name = 'auto_%s' % (free_id.get())
  51. free_id.inc()
  52. renames[name] = new_name
  53. new_graph[new_name] = []
  54. kind = kinds.get(name, None)
  55. if kind:
  56. new_kinds[new_name] = kind
  57. visited[name] = True
  58. edges = graph[name]
  59. for label, target in edges:
  60. if target[0] != '?':
  61. dfs(target)
  62. # rename nodes
  63. dfs('auto_initial_IP')
  64. # rename edges
  65. for n, edges in graph.iteritems():
  66. new_name = renames[n]
  67. for label, target in edges:
  68. if target[0] != '?':
  69. new_graph[new_name].append((label, renames[target]))
  70. else:
  71. new_graph[new_name].append((label, target))
  72. # sort nodes by name
  73. new_graph = new_graph.items()
  74. new_graph.sort(key=lambda x:x[0])
  75. f = open('output.dot', 'w')
  76. f.write('digraph G {\n')
  77. for n, edges in new_graph:
  78. kind = new_kinds.get(n, None)
  79. if kind:
  80. l = "{0}({1})".format(n, kind)
  81. f.write('{}[label={}];\n'.format(n, json.dumps(l)))
  82. else:
  83. f.write('{0}[label="{0}"];\n'.format(n))
  84. # include_id = 0
  85. for n, edges in new_graph:
  86. for label, target in edges:
  87. if target[0] == "?":
  88. target = target.replace('?', '_').replace('/', '_')
  89. # include_id += 1
  90. # t = target.replace('?', '').replace('/', '') + str(include_id)
  91. # include_id += 1
  92. f.write('{} -> {} [label={}];\n'.format(n, target, json.dumps(label)))
  93. f.write('}\n')
  94. output = []
  95. # output new file
  96. for n, edges in new_graph:
  97. kind = new_kinds.get(n, None)
  98. if kind:
  99. output.append("V %s(%s)\n" % (n, kind))
  100. else:
  101. output.append("N %s\n" % (n))
  102. for n, edges in new_graph:
  103. for label, target in edges:
  104. output.append("D %s,%s,%s\n" % (n, label, target))
  105. output = ''.join(output)
  106. output = output.replace("auto_0", "auto_initial_IP")
  107. return output
  108. if __name__ == "__main__":
  109. import sys
  110. input = open(sys.argv[1], 'r').read()
  111. output = postproc(input)
  112. print output