-
Notifications
You must be signed in to change notification settings - Fork 417
/
symtab06.py
113 lines (89 loc) · 2.96 KB
/
symtab06.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
from collections import OrderedDict
from spi import Lexer, Parser, NodeVisitor, BuiltinTypeSymbol, VarSymbol
class SymbolTable(object):
def __init__(self):
self._symbols = OrderedDict()
self._init_builtins()
def _init_builtins(self):
self.insert(BuiltinTypeSymbol('INTEGER'))
self.insert(BuiltinTypeSymbol('REAL'))
def __str__(self):
symtab_header = 'Symbol table contents'
lines = ['\n', symtab_header, '_' * len(symtab_header)]
lines.extend(
('%7s: %r' % (key, value))
for key, value in self._symbols.items()
)
lines.append('\n')
s = '\n'.join(lines)
return s
__repr__ = __str__
def insert(self, symbol):
print('Insert: %s' % symbol.name)
self._symbols[symbol.name] = symbol
def lookup(self, name):
print('Lookup: %s' % name)
symbol = self._symbols.get(name)
# 'symbol' is either an instance of the Symbol class or None
return symbol
class SemanticAnalyzer(NodeVisitor):
def __init__(self):
self.symtab = SymbolTable()
def visit_Block(self, node):
for declaration in node.declarations:
self.visit(declaration)
self.visit(node.compound_statement)
def visit_Program(self, node):
self.visit(node.block)
def visit_Compound(self, node):
for child in node.children:
self.visit(child)
def visit_NoOp(self, node):
pass
def visit_BinOp(self, node):
self.visit(node.left)
self.visit(node.right)
def visit_VarDecl(self, node):
type_name = node.type_node.value
type_symbol = self.symtab.lookup(type_name)
# We have all the information we need to create a variable symbol.
# Create the symbol and insert it into the symbol table.
var_name = node.var_node.value
var_symbol = VarSymbol(var_name, type_symbol)
# Signal an error if the table alrady has a symbol
# with the same name
if self.symtab.lookup(var_name) is not None:
raise Exception(
"Error: Duplicate identifier '%s' found" % var_name
)
self.symtab.insert(var_symbol)
def visit_Assign(self, node):
# right-hand side
self.visit(node.right)
# left-hand side
self.visit(node.left)
def visit_Var(self, node):
var_name = node.value
var_symbol = self.symtab.lookup(var_name)
if var_symbol is None:
raise Exception(
"Error: Symbol(identifier) not found '%s'" % var_name
)
if __name__ == '__main__':
text = """
program SymTab6;
var x, y : integer;
var y : real;
begin
x := x + y;
end.
"""
lexer = Lexer(text)
parser = Parser(lexer)
tree = parser.parse()
semantic_analyzer = SemanticAnalyzer()
try:
semantic_analyzer.visit(tree)
except Exception as e:
print e
print(semantic_analyzer.symtab)