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 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()