-
Notifications
You must be signed in to change notification settings - Fork 0
/
syntax_tree.py
163 lines (144 loc) · 5.48 KB
/
syntax_tree.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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
class Node:
def __init__(self, key, parent, index, value=None):
self.key = key
self.parent = parent
self.children = []
self.index = index
self.value = value
def add_child(self, keys):
for idx, item in enumerate(keys):
node = Node(item, self, idx)
self.children.append(node)
return self.children[0]
def advance(self):
node = self
while True:
if node.parent is not None:
if len(node.parent.children) - 1 == node.index:
node = node.parent
else:
break
else:
return node
cur = node.parent.children[node.index + 1]
while len(cur.children) != 0:
cur = cur.children[0]
return cur
def get_root(self):
node = self
while node.parent is not None:
node = node.parent
return node
@staticmethod
# Reference - https://stackoverflow.com/questions/30893895/how-to-print-a-tree-in-python
def print_tree(current_node, indent="", last='updown'):
nb_children = lambda node: node.index
size_branch = {child: nb_children(child) for child in current_node.children}
""" Creation of balanced lists for "up" branch and "down" branch. """
up = sorted(current_node.children, key=lambda node: nb_children(node))
down = []
while up and sum(size_branch[node] for node in down) < sum(size_branch[node] for node in up):
down.append(up.pop())
""" Printing of "up" branch. """
for child in up:
next_last = 'up' if up.index(child) == 0 else ''
next_indent = '{0}{1}{2}'.format(indent, ' ' if 'up' in last else '│', " " * len(current_node.key))
Node.print_tree(child, indent=next_indent, last=next_last)
""" Printing of current node. """
if last == 'up':
start_shape = '┌'
elif last == 'down':
start_shape = '└'
elif last == 'updown':
start_shape = ' '
else:
start_shape = '├'
if up:
end_shape = '┤'
elif down:
end_shape = '┐'
else:
end_shape = ''
text = current_node.key if current_node.key != '' else 'ϵ'
if current_node.value:
text = f"\"{current_node.value}\""
print('{0}{1}{2}{3}'.format(indent, start_shape, text, end_shape))
""" Printing of "down" branch. """
for child in down:
next_last = 'down' if down.index(child) is len(down) - 1 else ''
next_indent = '{0}{1}{2}'.format(indent, ' ' if 'down' in last else '│', " " * len(current_node.key))
Node.print_tree(child, indent=next_indent, last=next_last)
def get_symbol_table(self):
node = self.get_root()
scope = ["global"]
symbol_table = []
while node.children:
node = node.children[0]
symbol_table.append([node.value, "function", scope[:]])
scope.append(node.value)
node = node.advance()
while node.parent is not None:
if node.key in ["char", "int"]:
node_type = node.key
node = node.advance()
if node.key == "([a-z] | [A-Z])*":
symbol_table.append([node.value, node_type, list(scope)])
node = node.advance()
continue
elif node.key in ["IF", "ELSE"]:
scope.append(node.key)
elif node.key == "}":
scope.pop()
node = node.advance()
return symbol_table
def search_inorder(self):
node = self
if node.children:
return node.children[0]
while node.parent is not None:
if node.index != len(node.parent.children) - 1:
return node.parent.children[node.index + 1]
node = node.parent
return None
def get_left(self):
node = self
while node.index == 0:
node = node.parent
return node.parent.children[node.index - 1]
def get_right(self):
node = self
while True:
if len(node.parent.children) > node.index + 1:
break
else:
node = node.parent
return node.parent.children[node.index + 1]
def get_bt(self):
operators = ["=", "+", "*", ">"]
q = []
root = None
q.extend(self.children)
while True:
node = q.pop(0)
if node.key in operators:
if root is None:
if node.value:
root = Node(node.value, node.parent, node.index, node.value)
else:
root = Node(node.key, node.parent, node.index, node.value)
if len(root.children) == 0:
left = node.get_left()
root.children.append(left.get_bt())
right = node.get_right()
root.children.append(right.get_bt())
else:
for gc in node.children:
q.append(gc)
if len(q) == 0:
if root is None:
if node.value:
root = Node(node.value, node.parent, node.index, node.value)
else:
root = Node(node.key, node.parent, node.index, node.value)
break
return root