def main(input_file): if len(input_file.split('.')) == 1: if input_file[-1] == '/': input_file = input_file[:-1] output_file = join(input_file, input_file.split('/')[-1]) input_files = [ join(input_file, f) for f in listdir(input_file) if f.split('.')[1] == 'vm' and f != 'Sys.vm' and isfile(join(input_file, f)) ] input_files.insert(0, join(input_file, 'Sys.vm')) print('Input files: {}'.format(input_files)) else: input_files = [input_file] directory = '/'.join(input_file.split('/')[:-1]) output_file = join(directory, input_file.split('/')[-1].split('.')[0]) code_writer = CodeWriter(output_file) code_writer.write_init() for input_file in input_files: parser = Parser(input_file) code_writer.set_filename(input_file) n = 0 while parser.advance(): com_type = parser.command_type() print('LINE {}'.format(n)) print('\tcom type: {}'.format(com_type)) print('\tcommand: {}'.format(parser.command)) if com_type != parser.c_return: arg1 = parser.arg1() if com_type in [ parser.c_push, parser.c_pop, parser.c_function, parser.c_call ]: arg2 = parser.arg2() if com_type == parser.c_arithmetic: code_writer.write_arithmetic(arg1) elif com_type in [parser.c_pop, parser.c_push]: code_writer.write_push_pop(com_type, arg1, int(arg2)) elif com_type == parser.c_label: code_writer.write_label(arg1) elif com_type == parser.c_goto: code_writer.write_goto(arg1) elif com_type == parser.c_if: code_writer.write_if(arg1) elif com_type == parser.c_function: code_writer.write_function(arg1, arg2) elif com_type == parser.c_return: code_writer.write_return() elif com_type == parser.c_call: code_writer.write_call(arg1, arg2) n += 1 code_writer.close()
def main(): filename = sys.argv[1].split('.')[0] parser = Parser(filename) code = CodeWriter(filename) while(parser.has_more_commands()): parser.advance() command_type = parser.command_type() if command_type == 'C_ARITHMETIC': code.write_arithmetic(parser.arg1()) elif command_type == 'C_PUSH' or command_type == 'C_POP': code.write_push_pop(parser.command(), parser.arg1(), parser.arg2()) # print(parser.current_command) parser.close() code.close()
def main(): vm_filename = sys.argv[1] asm_filename = vm_filename.replace('.vm', '.asm') vm_file = open(vm_filename, 'r') asm_file = open(asm_filename, 'a') parser = Parser(vm_file) code_writer = CodeWriter(asm_file) while parser.has_more_commands(): parser.advance() if parser.command_type() == C_ARITHMETIC: code_writer.write_arithmetic(parser.arg1()) elif parser.command_type() == C_PUSH: code_writer.write_push_pop(C_PUSH, parser.arg1(), parser.arg2()) elif parser.command_type() == C_POP: code_writer.write_push_pop(C_POP, parser.arg1(), parser.arg2()) vm_file.close() code_writer.close()
def main(): # If there is an invalid number of arguments the program stops. if len(sys.argv) != 2: print("ERROR: Invalid number of arguments. Expected: file_name.vm ") exit(1) # the VM translator only accepts vm files to be translated into assembly files. elif sys.argv[1][-3:] != ".vm": print("ERROR: Invalid file type. Expected: vm file") exit(1) # Get the name of the file to be parsed from the arguments. input_file = sys.argv[1] # Creates a new parser to parse the file. parser = Parser(input_file) # Creates the code writer with the input file excluding the .vm part code_writer = CodeWriter(input_file[0:-3]) # Reads the whole file. while parser.has_more_commands(): parser.advance() # Gets the command type from the current command. command_type = parser.command_type() # If the command type is C_ARITHMETIC parses it to get the command and passes it to the code writer to add it to the output file if command_type == "C_ARITHMETIC": command = parser.arg1() code_writer.write_arithmetic(command) # If the command type is C_PUSH or C_POP parses it to get the segment and the index and passes it to the code writer to add it to the output file elif command_type == "C_PUSH" or command_type == "C_POP": segment = parser.arg1() index = parser.arg2() code_writer.write_push_pop(command_type, segment, index) del parser code_writer.close()
c.write_init() for filename in [files[sys_init]] + rest: # order matters # only parse .vm files if filename.find('.vm') != -1: c.set_filename(filename) p = Parser(BASE + filename) while p.has_more_lines(): p.advance() command = p.command_type() arg_1 = p.arg_1() arg_2 = p.arg_2() if command in ['C_PUSH', 'C_POP']: c.write_push_pop(command, arg_1, arg_2) if command == 'C_ARITHMETIC': c.write_arithmetic(arg_1) if command == 'C_GOTO': c.write_goto(arg_1) if command == 'C_IF': c.write_if(arg_1) if command == 'C_LABEL': c.write_label(arg_1) if command == 'C_FUNCTION': c.write_function(arg_1, arg_2) if command == 'C_RETURN': c.write_return()
class VMTranslator: def __init__(self, src: str): self.asm_file, self.vm_files = self._parse_files(src) print("Translate to %s." % self.asm_file) self.code_writer = CodeWriter(self.asm_file) def translates(self): for vm_file in self.vm_files: self._translate(vm_file) def _parse_files(self, file_path: str) -> (str, list): if not os.path.exists(file_path): raise IOError("No such file or directory.") if os.path.isfile(file_path) and file_path.endswith(VM_EXT): asm_file = file_path.replace(VM_EXT, ASM_EXT) vm_files = [file_path] elif os.path.isdir(file_path): dir_path = file_path[:-1] if file_path[-1] == "/" else file_path asm_file = dir_path + "/" + os.path.basename(dir_path) + ASM_EXT vm_files = self._find_all_files_with_ext(dir_path, "vm") else: raise IOError("No such file or directory.") return asm_file, vm_files def _find_all_files_with_ext(self, dir_path: str, ext: str) -> list: ext_files = [] suffix = os.extsep + ext.lower() for cur_dir, _, files in os.walk(dir_path): for file in files: if file.lower().endswith(suffix): ext_files.append(os.path.join(cur_dir, file)) return ext_files def _translate(self, vm_file: str): parser = Parser(vm_file) self.code_writer.set_filename(vm_file) self.code_writer.write("// ---------- %s ----------" % self.code_writer.current_vm_file) while parser.next_line(): self.code_writer.write("// " + parser.command_line()) if parser.command_type() == "C_ARITHMETIC": self.code_writer.write_arithmetic(parser.argn(0)) elif parser.command_type() == "C_PUSH": self.code_writer.write_push(parser.argn(1), parser.argn(2)) elif parser.command_type() == "C_POP": self.code_writer.write_pop(parser.argn(1), parser.argn(2)) elif parser.command_type() == "C_LABEL": self.code_writer.write_label(parser.argn(1)) elif parser.command_type() == "C_GOTO": self.code_writer.write_goto(parser.argn(1)) elif parser.command_type() == "C_IF_GOTO": self.code_writer.write_if_goto(parser.argn(1)) elif parser.command_type() == "C_FUNCTION": self.code_writer.write_function(parser.argn(1), int(parser.argn(2))) elif parser.command_type() == "C_CALL": self.code_writer.write_call(parser.argn(1), int(parser.argn(2))) elif parser.command_type() == "C_RETURN": self.code_writer.write_return() self.code_writer.write("") # empty line self.code_writer.write("// ------------------------------\n")
if __name__ == "__main__": if len(sys.argv) != 2: print(f"Usage: {sys.argv[0]} <{sys.argv[1]}>") files = [] if sys.argv[1].endswith('.vm'): files.append(sys.argv[1]) elif os.path.isdir(sys.argv[1]): files.extend(glob.glob("*.vm")) cw = CodeWriter(sys.argv[1].strip(".vm") + ".asm") print(f"Creating {sys.argv[1].strip('.vm') + '.asm'} ...") for f in files: p = Parser(f) cw.file_name = f while p.advance(): if p.command_type == CommandType.C_ARITHMETIC: cw.write_arithmetic(p.arg1()) elif p.command_type == CommandType.C_PUSH: cw.write_push_pop(CommandType.C_PUSH, segment_map[p.arg1()], p.arg2()) elif p.command_type == CommandType.C_POP: cw.write_push_pop(CommandType.C_POP, segment_map[p.arg1()], p.arg2()) print("Success.")