Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
lsbasi/part13/symtab04.py
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
97 lines (74 sloc)
2.46 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 __name__ == '__main__': | |
text = """ | |
program SymTab4; | |
var x, y : integer; | |
begin | |
x := x + y; | |
end. | |
""" | |
lexer = Lexer(text) | |
parser = Parser(lexer) | |
tree = parser.parse() | |
semantic_analyzer = SemanticAnalyzer() | |
semantic_analyzer.visit(tree) | |
print(semantic_analyzer.symtab) |