def main(debug, b_reg): """ in: bool debug, bool b register out: void """ ML = [] st = SymbolTable() if len(sys.argv) < 2: no_file_arg() input_file = sys.argv[1] name = os.path.splitext(input_file)[0] parsed = Parser(input_file, debug, b_reg) rom_address = 0 ram_address = 16 """ First pass """ while parsed.has_more_cmds(): if parsed.command_type() == "C_COMMAND" or parsed.command_type() == "A_COMMAND": rom_address += 1 elif parsed.command_type() == "L_COMMAND": st.add_entry(parsed.symbol(), rom_address) parsed.advance() parsed.reset() """ Second pass """ i = 0 while parsed.has_more_cmds(): cc = parsed.b_cc() # account for b reg command_type = parsed.command_type() if command_type == "A_COMMAND": """ Handle A commands. """ if st.contains(cc[1:]): ML.append(parsed.a_int_to_binary(st.get_address(cc[1:]))) elif parsed.cc_is_int(): ML.append(parsed.a_int_to_binary(cc)) elif not st.contains(cc[1:]): st.add_entry(cc[1:], ram_address) ML.append(parsed.a_int_to_binary(str(st.get_address(cc[1:])))) ram_address += 1 else: ML.append(parsed.c_to_binary(cc, command_type, st)) parsed.advance() i += 1 create_file(ML, name)
def main(): filename = sys.argv[1] output = open(filename.split('.')[0] + '.hack', 'w') firstPass = Parser(filename) symbolTable = SymbolTable() rom_address = 0 ramAddress = 16 # First pass adds L_COMMANDs and ROM addresses to symbol table while firstPass.hasMoreCommands(): firstPass.advance() command = firstPass.commandType() if command == 'A_COMMAND' or command == 'C_COMMAND': rom_address += 1 elif command == 'L_COMMAND': symbolTable.addEntry(firstPass.symbol(), rom_address) # When A_COMMAND is encountered: # if symbol is a digit write it to file # if symbol is not a digit, look it up in the symbol table. If it's there, write the address # if symbol is not a digit, look it up in the symbol table. If it is not there, add it then write the address secondPass = Parser(filename) while secondPass.hasMoreCommands(): secondPass.advance() command = secondPass.commandType() symbol = secondPass.symbol() if command == 'A_COMMAND' and symbol: if symbol.isdigit(): output.write('0' + '{0:015b}'.format(int(symbol)) + '\n') elif symbolTable.contains(symbol): symbolAddress = symbolTable.getAddress(symbol) output.write('0' + '{0:015b}'.format(int(symbolAddress)) + '\n') else: symbolTable.addEntry(symbol, ramAddress) ramAddress += 1 symbolAddress = symbolTable.getAddress(symbol) output.write('0' + '{0:015b}'.format(int(symbolAddress)) + '\n') else: dest = Code.dest(secondPass.dest()) jump = Code.jump(secondPass.jump()) comp = Code.comp(secondPass.comp()) if comp != None: output.write('111' + comp + dest + jump + '\n') output.close()
#------------------------------------------------------------------------------ # Main #------------------------------------------------------------------------------ #Builds the symbol table while par.hasMoreCommands(): par.advance() cType = par.commandType() #if the command type is a label if re.search('L_COMMAND',cType) is not None: temp_L = re.search('(.*)(;)(.*)',par.symbol()) symT.addEntry(temp_L.group(1),int(temp_L.group(3)),False) #if it is an adddress type command elif re.search('A_COMMAND',cType) is not None: if not symT.contains(par.symbol()): #explicitly defind address if re.search('^[0-9]+',par.symbol()) is not None: symT.addEntry(par.symbol(),int(par.symbol()),False) else: symT.addEntry(par.symbol(),user_def_count,True) #End loop OUT=open(out_file,'w') par2 = Parser(in_file,extended_op) toWrite='' output=''
class Main(object): def __init__(self, f): self.asm_file = f self.table = SymbolTable() self.data = self.read_file() self.parser = Parser(self.data) self.commands = self.parser.commands self.translator = Translator() self.filename = self.asm_file.split(".")[0] def read_file(self): with open(self.asm_file) as f: data = f.readlines() return data def write_file(self, output_lines): with open('%sassembled.hack' % self.filename, 'w') as output_file: for line in output_lines: output_file.write(line + '\n') def assemble(self): self.first_pass() output_lines = self.second_pass() self.write_file(output_lines) def first_pass(self): program_line = 0 for line in self.commands: # if we have encountered a label pseudocommand # check if it is in the table, if not assign it to value of next program line # don't increment program counter because this shouldn't count as a program line if line[0] == '(': if not self.table.contains(line[1:-1]): self.table.add_entry(line[1:-1], program_line) continue # if none of these conditions are hit, keep incrementing program line program_line += 1 def second_pass(self): translated_commands = [] next_available_RAM = 16 for line in self.commands: if line[0] == '@': symbol = line[1:] try: # translate directly if @ is referencing a specific value translated_commands.append('{0:016b}'.format(int(symbol))) continue except ValueError: pass # check if symbol is already in the symbol table and convert value to binary if self.table.contains(symbol): translated_commands.append('{0:016b}'.format( self.table.get_address(symbol))) # add symbol to symbol table, increment available RAM count, and translate to binary else: self.table.add_entry(symbol, next_available_RAM) next_available_RAM += 1 translated_commands.append('{0:016b}'.format( self.table.get_address(symbol))) elif line[0] == '(': continue else: translated_commands.append( self.translator.handle_C_instruction(line)) return translated_commands
class Assembler(): ''' Takes a single .asm file as input and outputs a .hack file with the same name. The assembling takes three passes. - Preprocess: Remove whitespace and comments - First Pass: Generate symbol table and remove symbolic labels - Second Pass: Translates the .asm file into a .hack file, line by line. ''' def __init__(self, filename): self._input = self.preprocess(filename) self._name = filename.split('/')[-1] self._name = self._name.split('.')[0] self._table = SymbolTable() self.first_pass() self._parser = Parser(self._input) self._output = [] self._code = Code() self.second_pass() self.write_output() def preprocess(self, filename): with open(filename, 'r') as temp: assembly = temp.readlines() temp = [] for line in assembly: # remove comments and white space line = line.split('//')[0].strip().replace(' ', '') if line: # if nonempty, then it should contain valid asm temp += [line] return temp def first_pass(self): rom_addr = 0 temp = [] for line in self._input: if '(' in line: symbol = line[1:-1] self._table.add_entry(symbol, rom_addr) else: temp += [line] rom_addr += 1 self._input = temp def second_pass(self): while self._parser.has_more_commands(): self._parser.advance() if self._parser.command_type() == 'A': # A type command value = self._parser.symbol() if set(value) <= set('0123456789'): # symbol is a number value = int(value) elif self._table.contains(value): # symbol is a label value = self._table.get_address(value) else: # symbol is a variable self._table.add_entry(value) value = self._table.get_address(value) self._output += ['0' + "{0:015b}".format(value) + '\n'] elif self._parser.command_type() == 'C': # C type command self._output += [ '111' + self._code.comp(self._parser.comp()) + self._code.dest(self._parser.dest()) + self._code.jump(self._parser.jump()) + '\n' ] def write_output(self): with open('hack/' + self._name + '.hack', 'w') as temp: temp.writelines(self._output) print(self._name + '.asm', 'translated to', 'hack/' + self._name + '.hack')