def main(): output_list = [] if len(sys.argv) == 2: file_name = str(os.path.splitext(sys.argv[1])[0]) file_ext = os.path.splitext(sys.argv[1])[1] if len(sys.argv) != 2 or file_ext != ".vm": print("Usage: translator.py <inputFile>.vm") return try: parser = Parser(file_name, file_ext) writer = CodeWriter(file_name) except IOError as e: print(e) return else: while parser.hasMoreCommands(): parser.advance() cmd = parser.command_type() if cmd != "C_RETURN": argument1 = parser.arg1() if cmd in ["C_POP", "C_PUSH", "C_FUNCTION", "C_CALL"]: argument2 = parser.arg2() if cmd == "C_ARITHMETIC": writer.write_arithmetic(argument1) if cmd in ["C_POP", "C_PUSH"]: writer.write_push_pop(cmd, argument1, argument2) writer.close()
class VMTranslator(): ''' Manages the translation effort, bridging the gap between the Parser and Codewriter objects. A new Parser is created for each file in the directory. ''' def __init__(self, filename): if os.path.isdir(filename): self._files = [ filename + '/' + x for x in os.listdir(filename) if x.endswith(".vm") ] self._isdir = True self._name = filename + '/' + filename.split('/')[-1] + '.asm' elif os.path.isfile(filename) and filename.endswith('.vm'): self._files = [filename] self._isdir = False self._name = filename.replace('.vm', '.asm') else: self._files = list() self._isdir = False return self._output = [] self._code = CodeWriter(self._name) if self._isdir: self._code.write_init() for file in self._files: self._parser = Parser(file) self._code.filename(file.replace('.vm', '').split('/')[-1]) self.translate() self._code.close() def translate(self): # using input from parser, translate and output while self._parser.has_more_commands(): self._parser.advance() if self._parser.command_type() in ['C_ARITHMETIC', 'C_BOOLEAN']: self._code.write_arithmetic(self._parser.command()) elif self._parser.command_type() in ['C_POP', 'C_PUSH']: self._code.write_pushpop(self._parser.command_type(), self._parser.arg1(), self._parser.arg2()) elif self._parser.command_type() == 'C_LABEL': self._code.write_label(self._parser.arg1()) elif self._parser.command_type() == 'C_GOTO': self._code.write_goto(self._parser.arg1()) elif self._parser.command_type() == 'C_IF': self._code.write_if(self._parser.arg1()) elif self._parser.command_type() == 'C_FUNCTION': self._code.write_function(self._parser.arg1(), self._parser.arg2()) elif self._parser.command_type() == 'C_CALL': self._code.write_call(self._parser.arg1(), self._parser.arg2()) elif self._parser.command_type() == 'C_RETURN': self._code.write_return()
def translate_file(vm_file, asmfile): current_file_name = os.path.basename(vm_file)[:-3] # Initiate list of functions/files names and variables and append current file global_variables.function_list.append(current_file_name) with open(vm_file, 'r') as vmfile: # Create assembly file to receive translated code assembly_file = open(asmfile, 'a') parser = Parser() assembly_code = "" code_writer = CodeWriter(current_file_name) for line in vmfile: if is_blank_or_is_comment(line): pass else: command = parser.clean_line(line) command_type = parser.command_type(command) if command_type == "C_ARITHMETIC": assembly_code = code_writer.write_arithmetic(command) elif command_type in ["C_LABEL", "C_GOTO", "C_IF"]: command_args = parser.command_args(command) assembly_code = code_writer.write_control_flow( command_args) elif command_type in ["C_CALL", "C_RETURN", "C_FUNCTION"]: command_args = parser.command_args(command) assembly_code = code_writer.write_subroutines(command_args) else: command_args = parser.command_args(command) assembly_code = code_writer.write_push_pop(command_args) assembly_file.write(assembly_code) assembly_file.close() # Reset list of functions processed in the current file global_variables.function_list.clear()
def main(): arg_len = len(sys.argv) file_list = [] output_file = "" parsers = [] if arg_len == 1: dir_name = os.getcwd() output_file = dir_name + '/' + dir_name.split('/')[-1] + ".asm" for f in os.listdir(dir_name): if f.endswith(".vm"): file_list.append(f) if not file_list: print("Error, no .vm files in current directory") return elif arg_len == 2: if os.path.isdir(sys.argv[1]): output_file = sys.argv[1] + sys.argv[1].split('/')[-2] + ".asm" for f in os.listdir(sys.argv[1]): if f.endswith(".vm"): file_list.append(f) if not file_list: print("Error, no .vm files in given directory") return file_list = [sys.argv[1] + "/" + f for f in file_list] else: if os.path.splitext(sys.argv[1])[1] != ".vm": print("Error, .vm file not specified") return else: file_list.append(sys.argv[1]) output_file = os.path.splitext(sys.argv[1])[0] + ".asm" try: writer = CodeWriter(output_file) except IOError as e: print("In codewriter: ") print(e) return else: try: parsers = [Parser(f) for f in file_list] except IOError as e: print("In parsers: ") print(e) return else: writer.write_init() for p in parsers: writer.set_file_name(p.static_name) while p.hasMoreCommands(): p.advance() cmd = p.command_type() if cmd != "C_RETURN": argument1 = p.arg1() if cmd in ["C_POP", "C_PUSH", "C_FUNCTION", "C_CALL"]: argument2 = p.arg2() if cmd == "C_ARITHMETIC": writer.write_arithmetic(argument1) elif cmd in ["C_POP", "C_PUSH"]: writer.write_push_pop(cmd, argument1, argument2) elif cmd == "C_LABEL": writer.write_label(argument1) elif cmd == "C_GOTO": writer.write_goto(argument1) elif cmd == "C_IF": writer.write_if(argument1) elif cmd == "C_FUNCTION": writer.write_function(argument1, int(argument2)) elif cmd == "C_CALL": writer.write_call(argument1, argument2) elif cmd == "C_RETURN": writer.write_return() writer.close()