def _visit_func_decl(self, node: ASTNode): # Only for member function node.record = Record( node.children[0].token.lexeme, SymbolType(node.children[2].token.lexeme, []), RecordType.FUNCTION, node.children[0].token.location, params=[param.record for param in node.children[1].children], )
def _visit_func_param(self, node: ASTNode): node.record = Record( node.children[1].token.lexeme, # ID SymbolType( node.children[0].token.lexeme, [child.token for child in node.children[2].children], ), RecordType.PARAM, node.children[1].token.location, )
def _visit_var_decl(self, node: ASTNode): node.record = Record( node.children[1].token.lexeme, # ID SymbolType( node.children[0].token.lexeme, [child.token for child in node.children[2].children], ), None, node.children[1].token.location, )
def _type_for_data_member( self, node: ASTNode, types: List[SymbolType], records: List[Record], is_first: bool, ) -> SymbolType: token = node.children[0].token record = next( (r for r in records if r.record_type in DATA_RECORD_TYPES), None, ) if record is None: self.error( 'Use of undeclared {type} "{name}"'.format( type="local variable" if is_first else "data member", name=token.lexeme, ), token.location, ) return None index_types = types or [] if len(index_types) > len(record.type.dims) or any( type_ != SymbolType(INT, []) for type_ in index_types): self.error( 'Invalid indexing for "{name}", type is "{type}"'.format( name=token.lexeme, type=record.format_type()), token.location, ) return None if index_types: # Reserve space for offset calculation node.temp_record = Record("", SymbolType(INT, []), RecordType.TEMP, None) self.scope.insert(node.temp_record) node.record = record return SymbolType(record.type.base, record.type.dims[len(index_types):])
def _visit_main(self, node: ASTNode): table = SymbolTable("main") for child in node.children[0].children: # Locals table.insert(child.record) node.record = Record( "main", SymbolType("void", []), RecordType.FUNCTION, node.token.location, params=[], table=table, )
def _visit_func_def(self, node: ASTNode): name = node.children[1].token.lexeme table = SymbolTable(name, is_function=True) params = [param.record for param in node.children[2].children] for param in params: table.insert(param) for child in node.children[4].children: # Locals table.insert(child.record) node.record = Record( name, SymbolType(node.children[3].token.lexeme, []), RecordType.FUNCTION, node.children[1].token.location, params=params, table=table, ) scope = node.children[0].token if scope: parent = BaseType(scope.lexeme).table if not parent: self.error( 'Use of undeclared class "{name}"'.format( name=scope.lexeme), scope.location, ) return records = parent.entries.get(name, []) record = next( (r for r in records if r.record_type == RecordType.FUNCTION and equal_params(r.params, params) and r.type.base is node.record.type.base), None, ) if not record: self.error( 'Member function "{scope}::{name}{type}" is defined but has not been declared' .format(scope=scope.lexeme, name=name, type=node.record.format_type()), scope.location, ) return record.table = table # Attach table on existing record in the class table table.inherits = [BaseType(scope.lexeme)] table.name = scope.lexeme + "::" + table.name node.record = record else: GLOBALS.insert(node.record)
def _visit_rel_expr(self, node: ASTNode, types: List[SymbolType]) -> SymbolType: if self._binary_op(node, types) is None: return None return SymbolType(BOOLEAN, [])
def _visit_literal(self, node: ASTNode, types: List[SymbolType]) -> SymbolType: if node.token.token_type == L.INTEGER_LITERAL: return SymbolType(INT, []) return SymbolType(FLOAT, [])