class SymbolVisitor(Visitor): def __init__(self, file=stderr): self.table = SymbolTable(file=file) self.output = file @staticmethod def toTypeList(node): types = [] if node.name == 'TYPE': # could have a modifier AND a type if len(node.children) > 0: for child in node.children: if child.data is not None: types.append(child.data) else: types.append(node.data) return tuple(types) def visit(self, node): node.scopestack = tuple(self.table.getCurrentScopeStack()) if node.name == 'DECL': # DECL is the important one for processing variable instantion typelist = self.toTypeList(node.children[0]) self.table.enterSymbol(node.children[1].data, typelist) node.typelist = typelist super().visit(node) elif node.name == 'MULTI_ASSIGN' or node.name == 'MULTI': typelist = node.parent.typelist # typelist = self.toTypeList(node.children[0]) self.table.enterSymbol(node.children[0].data, typelist) node.typelist = typelist super().visit(node) elif node.name == 'CODEBLOCK': self.table.openScope() node.accept(self) self.table.closeScope() elif node.name == 'ASSIGN': # Check for const correctness # is node.data writable? syme = self.table.retrieveScope(node.children[0].data) if syme is None: # This error will be caught when the recursion to VALUE is found pass else: if 'const' in syme.symtype: # You cannot change that!!! print("Symbol %s cannot be assigned in scope %i" % (node.children[0].data, self.table.getCurrentScope()), file=self.output) self.table.errors = True node.accept(self) elif node.name == "VALUE" or node.name == "IDENTIFIER": # Check that the symbol is accessible in this scope, including const correctness if type(node.data) is str and self.table.retrieveScope(node.data) is None: print("The symbol %s is not accessible in scope %i" % (node.data, self.table.getCurrentScope()), file=self.output) self.table.errors = True else: node.accept(self) return self.table