Permalink
Cannot retrieve contributors at this time
from spi import Lexer, Parser, NodeVisitor, BuiltinTypeSymbol, VarSymbol | |
class SymbolTable(object): | |
def __init__(self): | |
self._symbols = {} | |
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) | |
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 SymTab5; | |
var x : integer; | |
begin | |
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) |