-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathpl1_graphviz.py
executable file
·138 lines (110 loc) · 3.6 KB
/
pl1_graphviz.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/env python
from pl1_node_visitor import *
import sys
import pl1_parser
import StringIO
import os
GraphHeader = '''
digraph finite_state_machine {
rankdir=TB;
size="8,5"
'''
GraphFooter = '''
}
'''
class GraphPrinter(NodeVisitor):
def __init__(self):
self.buf = None
self.next = 0
self.nodes = {}
self.stack = []
self.procedures = {}
def push(self, node):
self.stack.append(node)
if not self.nodes.has_key(id(node)):
self.nodes[id(node)] = "%s_%d" % (node[0], self.next,)
self.next += 1
return self.nodes[id(node)]
def parent_id(self):
parent = self.stack[-2]
return self.nodes[id(parent)]
def pop(self):
self.stack.pop()
def generate_graph(self, program):
self.buf = StringIO.StringIO()
self.buf.write(GraphHeader)
self.visit_node(program)
self.buf.write(GraphFooter)
contents = self.buf.getvalue()
self.buf.close
self.buf = None
return contents
def accept_program(self, node):
node_id = self.push(node)
self.buf.write(" node [shape=doublecircle,label=\"%s\",color=green]; %s;\n" % (node[0], node_id,))
NodeVisitor.accept_node(self, node)
self.pop()
def accept_node(self, node):
node_id = self.push(node)
parent_id = self.parent_id()
self.buf.write(" node [shape=circle,label=\"%s\",color=black]; %s -> %s;\n" % (node[0], parent_id, node_id,))
NodeVisitor.accept_node(self, node)
self.pop()
def accept_define(self, node):
node_id = self.push(node)
parent_id = self.parent_id()
label = "%s = %d" % node[1:]
self.buf.write(" node [shape=circle,label=\"%s\",color=black]; %s -> %s;\n" % (label, parent_id, node_id,))
NodeVisitor.accept_node(self, node)
self.pop()
def accept_condition(self, node):
node_id = self.push(node)
parent_id = self.parent_id()
self.buf.write(" node [shape=diamond,label=\"%s\",color=orange]; %s -> %s;\n" % (node[2], parent_id, node_id,))
NodeVisitor.accept_node(self, node)
self.pop()
def accept_name(self, node):
node_id = self.push(node)
parent_id = self.parent_id()
self.buf.write(" node [shape=square,label=\"%s\",color=blue]; %s -> %s;\n" % (node[1], parent_id, node_id,))
self.pop()
def accept_number(self, node):
node_id = self.push(node)
parent_id = self.parent_id()
self.buf.write(" node [shape=square,label=\"%d\",color=blue]; %s -> %s;\n" % (node[1], parent_id, node_id,))
self.pop()
def accept_procedure(self, node):
node_id = self.push(node)
self.procedures[node[1]] = node_id
parent_id = self.parent_id()
self.buf.write(" node [shape=trapezium,label=\"%s\",color=purple]; %s -> %s;\n" % (node[1], parent_id, node_id,))
NodeVisitor.accept_node(self, node)
self.pop()
def accept_expression(self, node):
node_id = self.push(node)
parent_id = self.parent_id()
self.buf.write(" node [shape=circle,label=\"EXPR\",color=blue]; %s -> %s;\n" % (parent_id, node_id,))
NodeVisitor.accept_node(self, node)
self.pop()
def accept_call(self, node):
node_id = self.push(node)
parent_id = self.parent_id()
proc_id = self.procedures[node[1]]
label = "CALL |{%s}" % node[1]
self.buf.write(" node [shape=record,label=\"%s\",color=purple]; %s -> %s;\n" % (label, parent_id, node_id,))
self.pop()
def accept_term(self, node):
NodeVisitor.accept_node(self, node)
if __name__ == '__main__':
code = sys.stdin.read()
parser = pl1_parser.Parser()
parser.input(code)
program = parser.p_program()
visitor = GraphPrinter()
contents = visitor.generate_graph(program)
with open('graph.dot', 'w') as f:
f.write(contents)
print "Generating Graph..."
os.system("dot -v -Tpdf -ograph.pdf graph.dot")
print "Opening Graph..."
os.system("open graph.pdf")