-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtreevis.py
More file actions
133 lines (123 loc) · 3.55 KB
/
treevis.py
File metadata and controls
133 lines (123 loc) · 3.55 KB
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
from graphviz import Digraph
import string
'''
This file contains two classes:
(1) a recursive SYNTAX tree maker
(2) a recursive PARSE tree maker
that both use graphviz's Digraph functionality
to render outputs of the parsed lines.
'''
class syntaxTreeMaker:
'This class is used to produce syntax trees.'
# class instantiation variables
def __init__(self):
self.edge_list = []
self.dot = Digraph(comment="")
# list of uppercase alphabet so nodes generator can uniquely name
self.alpha = []
for s in string.ascii_uppercase:
self.alpha.append(s)
# tree generator using graphyviz library
def generate(self, orig_tup, count):
self.dot = Digraph(comment=str(orig_tup))
self.treefy(orig_tup)
self.dot.edges(self.edge_list)
self.fig_title = r"\n\nSyntax tree for\n"+str(orig_tup)
self.dot.attr(label=self.fig_title)
self.dot.format = "png"
self.dot.render('output/'+str(count)+'_syntax.gv', view=True)
# Funky recursive tree generating function
def treefy(self, tup):
p = tup[0]
n_p = self.alpha.pop()
lc = tup[1]
rc = tup[2]
self.dot.node(n_p, str(p))
if type(lc) == tuple:
call_tup = self.treefy(lc)
lcn = call_tup[0]
n_lcn = call_tup[1]
self.dot.node(n_lcn,str(lcn))
self.edge_list.append(n_p+n_lcn)
else:
n_lc = self.alpha.pop()
self.dot.node(n_lc,str(lc))
self.edge_list.append(n_p+n_lc)
if type(rc) == tuple:
call_tup = self.treefy(rc)
rcn = call_tup[0]
n_rcn = call_tup[1]
self.dot.node(n_rcn,str(rcn))
self.edge_list.append(n_p+n_rcn)
else:
n_rc = self.alpha.pop()
self.dot.node(n_rc,str(rc))
self.edge_list.append(n_p+n_rc)
return (p, n_p)
class parseTreeMaker:
'This class is used to produce parse trees.'
# class instantiation variables
def __init__(self):
self.edge_list = []
self.dot = Digraph(comment="")
# list of uppercase alphabet so nodes generator can uniquely name
self.alpha = []
for s in string.ascii_uppercase:
self.alpha.append(s)
# tree generator using graphyviz library
def generate(self, orig_tup, count):
self.dot = Digraph(comment=str(orig_tup))
self.treefy(orig_tup)
self.dot.edges(self.edge_list)
self.fig_title = r"\n\nParse tree for line\n"+str(orig_tup)
self.dot.attr(label=self.fig_title)
self.dot.format = "png"
self.dot.render('output/'+str(count)+'_parse.gv', view=True)
# Funky recursive tree generating function
def treefy(self, tup):
p = str(tup)
n_p = self.alpha.pop()
op = tup[0]
parse_type = 'factor'
if op == 'times' or op == 'divide':
parse_type = 'term'
elif op == 'plus' or op == 'minus':
parse_type = 'expression'
elif op == 'equals':
parse_type = 'assign'
n_op = self.alpha.pop()
lc = tup[1]
rc = tup[2]
self.dot.node(n_p, parse_type)
# Left child
if type(lc) == tuple:
call_tup = self.treefy(lc)
lcn = call_tup[0]
n_lcn = call_tup[1]
self.dot.node(n_lcn,str(lcn))
self.edge_list.append(n_p+n_lcn)
else:
n_lc = self.alpha.pop()
n_lc_t = self.alpha.pop()
self.dot.node(n_lc,"factor")
self.dot.node(n_lc_t,str(lc))
self.edge_list.append(n_p+n_lc)
self.edge_list.append(n_lc+n_lc_t)
# Central operation
self.dot.node(n_op, str(op))
self.edge_list.append(n_p+n_op)
# Right child
if type(rc) == tuple:
call_tup = self.treefy(rc)
rcn = call_tup[0]
n_rcn = call_tup[1]
self.dot.node(n_rcn,str(rcn))
self.edge_list.append(n_p+n_rcn)
else:
n_rc = self.alpha.pop()
n_rc_t = self.alpha.pop()
self.dot.node(n_rc,"factor")
self.dot.node(n_rc_t,str(rc))
self.edge_list.append(n_p+n_rc)
self.edge_list.append(n_rc+n_rc_t)
return (parse_type, n_p)