def main(): input_path = sys.argv[FILE_POS] if isdir(input_path): input_list = [ input_path + "/" +f for f in listdir(input_path) if (isfile(join(input_path, f))) and (f.endswith(".vm")) ] # check if we're getting a path or something else index = input_path.rfind("/") name = input_path[index + 1:] output_file_name = input_path + "/" + name + ".asm" else: input_list = [input_path] index = input_path.index(".vm") output_file_name = input_path[:index] + ".asm" code_writer = CodeWriter(output_file_name) for input_file in input_list: parser = Parser(input_file) code_writer.set_file_name(input_file) while parser.has_more_commands(): command = parser.advance() if parser.command_type() == C_ARITHMETIC: code_writer.write_arithmetic(command) if (parser.command_type() == C_PUSH) or (parser.command_type() == C_POP): code_writer.write_push_pop(parser.command_type(), parser.arg1(), parser.arg2()) code_writer.close()
class VMtranslator(object): def __init__(self, input_file_path): self.input_file_path = input_file_path if not os.path.isdir(input_file_path): self.code_writer = CodeWriter(input_file_path.replace(".vm", ".asm")) else: file_name = input_file_path.split("/") file_name = file_name[len(file_name)-1] file_name = file_name.split("\\") file_name = file_name[len(file_name)-1] path = os.path.join(input_file_path, file_name+".asm") self.code_writer = CodeWriter(path) def translate(self, file_name): name = file_name.split(".vm")[0] self.parser = Parser.Parser(os.path.join(self.input_file_path, file_name)) self.code_writer._set_file_name(name) while self.parser.has_more_commands(): self.parser.advance() self._gen_command() self.code_writer.close() def _get_number_of_arguments(self, command_type): if command_type == Parser.C_PUSH or command_type == Parser.C_POP: return 2 if command_type == Parser.C_ARITHMETIC: return 0 return 0 def _gen_command(self): command_type = self.parser.command_type() if command_type == Parser.C_PUSH or command_type == Parser.C_POP: self.code_writer.WritePushPop(self.parser.current_commands[0], self.parser.arg1(), self.parser.arg2()) elif command_type == Parser.C_ARITHMETIC: self.code_writer.WriteArithmetic(self.parser.arg1())
class VMtranslator(object): def __init__(self, input_file_path): self.input_file_path = input_file_path self.code_writer = CodeWriter(input_file_path.replace(".vm", ".asm")) def translate(self): self.parser = Parser.Parser(self.input_file_path) while self.parser.has_more_commands(): self.parser.advance() self._gen_command() self.code_writer.close() def _gen_command(self): command_type = self.parser.command_type() command_handler, args_amount = { Parser.C_PUSH : [self.code_writer.write_push, 2], Parser.C_POP : [self.code_writer.write_pop, 2], Parser.C_ARITHMETIC : [self.code_writer.write_arithmetic, 1], Parser.C_IF : [self.code_writer.write_if, 1], Parser.C_LABEL : [self.code_writer.write_label, 1], Parser.C_RETURN : [self.code_writer.write_return, 0], Parser.C_GOTO : [self.code_writer.write_goto, 1], Parser.C_FUNCTION : [self.code_writer.write_function, 2], Parser.C_CALL : [self.code_writer.write_call, 2] }[command_type] self._handle_command(command_handler, args_amount) def _handle_command(self, command_handler, args_amount): if args_amount == 2: command_handler(self.parser.arg1(), self.parser.arg2()) return if args_amount == 1: command_handler(self.parser.arg1()) return command_handler()
class VMTranslator: def __init__(self, path): is_directory = False if os.path.isfile(path): self.files = [path] elif os.path.isdir(path): self.files = [ os.path.join(path, file) for file in os.listdir(path) if file.endswith('.vm') ] is_directory = True self.parser = None self.writer = CodeWriter(path, is_directory) def translate(self): for file in self.files: self.parser = Parser(file) self.writer.update_classname_by_filename(file) while self.parser.has_more_commands(): self.parser.advance() self.writer.write(self.parser.command_type(), self.parser.arg1(), self.parser.arg2(), self.parser.vm_command()) self.parser.close() self.writer.close()
class VMtranslator(object): '''translator .vm file to .asm file if more than one .vm file is given, bootstrap code will be written at the beginning of .asm file method: gen() ''' def __init__(self, file): if file.endswith('.vm') and os.path.isfile(file): self.__infilelist = [file] self.__outfilename = file[:-2] + 'asm' else: if not os.path.isdir(file): print('input should be a ".vm" file or a directory') sys.exit() self.__infilelist = glob.glob(os.path.join(file, '*.vm')) self.__outfilename = os.path.join( file, os.path.basename(os.path.abspath(file)) + '.asm') if self.__infilelist == []: print('no ".vm" file found in the given directory') sys.exit() self.__code = CodeWriter(self.__outfilename) def gen(self): '''generate assembly code and stores in .asm file ''' if len(self.__infilelist) > 1: self.__code.writeInit() for infile in self.__infilelist: parser = Parser(infile) while parser.hasnext(): command = parser.next() self.__code.parse(command) self.__code.close()
def main(): args = [x for x in sys.argv] if len(args) < 2: raise Exception( "Error[7]: No file/dir name provided \"Usage: python VMTranslator.py file.vm\"" ) if not os.path.isfile(args[1]) and not os.path.isdir(args[1]): raise FileNotFoundError("Error[8]: \"" + args[1] + "\" does not exist") input_files = [args[1]] output_file_name = os.path.basename(os.path.abspath(args[1])).split(".") if len(output_file_name) > 1: output_file_name.pop() output_file_name = ".".join(output_file_name) if os.path.isdir(input_files[0]): input_files = [ f for f in os.listdir(input_files[0]) if os.path.isfile(os.path.join(input_files[0], f)) ] input_files = [f for f in input_files if f.split(".")[-1] == "vm"] input_files = [os.path.abspath(f) for f in input_files] print(input_files) print(output_file_name) code_writer = CodeWriter(output_file_name) for file_name in input_files: parser = Parser(file_name) code_writer.setFileName(file_name) while parser.hasMoreCommands(): parser.advance() arg1 = None arg2 = None if parser.commandType() != COMMAND_TYPES["C_RETURN"]: arg1 = parser.arg1() if parser.commandType() == COMMAND_TYPES["C_PUSH"] or \ parser.commandType() == COMMAND_TYPES["C_POP"] or \ parser.commandType() == COMMAND_TYPES["C_FUNCTION"] or \ parser.commandType() == COMMAND_TYPES["C_CALL"]: arg2 = parser.arg2() if parser.commandType( ) == COMMAND_TYPES["C_ARITHMETIC"] and arg1 is not None: code_writer.writeArithmetic(arg1) if (parser.commandType() == COMMAND_TYPES["C_PUSH"] or \ parser.commandType() == COMMAND_TYPES["C_POP"]) and \ arg1 is not None and arg2 is not None: code_writer.writePushPop(parser.commandType(), arg1, arg2) code_writer.close()
def main(): #make sure they used the program right if len(sys.argv) != 2: print( "usage: python VMtranslator.py <some .vm file or a directory with .vm files in it>" ) return #holds the open file descriptors to pass to the Parser constructor fileHandles = [] inputPath = sys.argv[1] outputPath = "" #see if file or directory if inputPath.endswith(".vm"): #file vmFile = open(inputPath, 'r') fileHandles.append(vmFile) #set output path to be the vm file but with .asm extension outputPath = inputPath.replace(".vm", ".asm") elif os.path.isdir(inputPath): #make sure that the path doesn't end in a slash for a directory if inputPath.endswith("/"): inputPath = inputPath[:-1] #get .vm files and open them from directory for file in os.listdir(inputPath): if file.endswith(".vm"): vm = open(os.path.join(inputPath, file), 'r') fileHandles.append(vm) #outputpath is the path/directoryName.asm outputPath = inputPath + "/" + os.path.basename(inputPath) + ".asm" else: #error print( "You must enter a single .vm file or a directory with .vm files in it" ) #instantiate the codewriter with the correct output path writer = CodeWriter(outputPath) #run through all the .vm files we have for file in fileHandles: #make a new parser for each .vm file parser = Parser(file) #make sure to give the writer the current file name for static memory access stuff writer.setFileName(os.path.basename(file.name)) #write either arithmetic or memory access commands while (parser.hasMoreCommands()): if parser.commandType() == "C_ARITHMETIC": writer.writeArithmetic(parser.arg1()) elif parser.commandType() == "C_PUSH" or parser.commandType( ) == "C_POP": writer.writePushPop(parser.commandType(), parser.arg1(), parser.arg2()) parser.advance() #close the output file writer.close()
def main(): inputFileName = getInputName() isDirectory = os.path.isdir(inputFileName) if isDirectory: files = os.listdir(inputFileName) vmFiles = filter(isVMFile, files) listOfFiles = list( map(lambda fileName: inputFileName + "/" + fileName, vmFiles)) outputFileName = trimFile(inputFileName) writer = CodeWriter(inputFileName + "/" + outputFileName) if len(listOfFiles) > 1: writer.bootstrap() else: listOfFiles = [inputFileName] outputFileName = trimFile(inputFileName) writer = CodeWriter(outputFileName) for currentFile in listOfFiles: print("File to be parsed: {}".format(currentFile)) writer.setNewInputFile(trimFile(currentFile)) parser = Parser(currentFile) while parser.hasMoreCommands(): parser.advance() command = parser.getCommand() if parser.isArithmetic(): writer.writeArithmetic(command) elif parser.isPush() or parser.isPop(): writer.writePushPop(command) elif parser.isLabel(): writer.writeLabel(command) elif parser.isGoto(): writer.writeGoto(command) elif parser.isIf(): writer.writeIf(command) elif parser.isFunction(): writer.writeFunction(command) elif parser.isCall(): writer.writeCall(command) elif parser.isReturn(): writer.writeReturn(command) elif parser.isComment() or parser.isBlankLine(): continue else: raise Exception("Command not supported") parser.close() writer.close() print("VMTranslator finished.")
def translate(path): """translate vm language in a vm file or files in the path to asm language in other files. path: dirpath or filepath """ has_sys_init, filepaths, outpath = retrive_files(path) writer = CodeWriter(outpath) if has_sys_init: writer.write_sys_init() for filepath in filepaths: filename = os.path.basename(filepath) writer.set_file_name(filename) parser = Parser(filepath) translate_file(parser, writer) writer.close()
def main(): """ The main method. Checks for valid input. Executes parsing on given file/dir and uses the codeWriter to create an assembly file in given path. :return: """ if len(sys.argv) != 2: print("This script takes 1 argument: a filename or a directory name.") return current_path = sys.argv[1] if isfile(current_path): if not current_path.endswith(INPUT_FILE_SUFFIX): print("Not an asm file.") return vm_files = [current_path] current_path = current_path[:-3] + OUTPUT_FILE_SUFFIX else: if not current_path.endswith('/'): current_path += '/' vm_files = [ current_path + f for f in listdir(current_path) if isfile(join(current_path, f)) and f.endswith(INPUT_FILE_SUFFIX) ] dir_name = current_path.split('/') output_name = dir_name[-2] current_path += output_name + OUTPUT_FILE_SUFFIX if not vm_files: print("No files with the .vm file extension found.") return code_writer = CodeWriter(open(current_path, 'w')) for file in vm_files: curr_parser = Parser(file) filename = file.split('/')[-1] filename = filename[:filename.rfind('.')] code_writer.set_filename(filename) process(curr_parser, code_writer) code_writer.close()
class Processor(): def __init__(self, filename): file = splitext(filename)[0] self.parser = Parser(file + '.vm') self.code = CodeWriter(file + '.asm') def start(self): while self.parser.hasMoreCommands(): if self.parser.commandType()[0] in [Command.C_PUSH, Command.C_POP]: self.code.writePushPop(self.parser.commandType()[0], self.parser.arg1(), self.parser.arg2()) elif self.parser.commandType()[0] == Command.C_ARITHMETIC: self.code.writeArithmetic(self.parser.commandType()[1]) self.parser.advance() self.code.close()
class VMtranslator(object): def __init__(self, input_file_path): self.input_file_path = input_file_path self.code_writer = CodeWriter(input_file_path.replace(".vm", ".asm")) def translate(self): self.parser = Parser.Parser(self.input_file_path) while self.parser.has_more_commands(): self.parser.advance() self._gen_command() self.code_writer.close() def _gen_command(self): command_type = self.parser.command_type() if command_type == Parser.C_PUSH: self.code_writer.write_push(self.parser.arg1(), self.parser.arg2()) elif command_type == Parser.C_POP: self.code_writer.write_pop(self.parser.arg1(), self.parser.arg2()) elif command_type == Parser.C_ARITHMETIC: self.code_writer.write_arithmetic(self.parser.arg1())
def translateVM(path): files = getfiles(path) dir_var = None if isdir(path): dir_var = split(path)[1] codewriter = CodeWriter(files[0], dir_var) for cur_file in files: codewriter.setfilename(cur_file) Parser.initialize(cur_file) Parser.open_file() Parser.advance() while Parser.has_more_commands(): command_type = Parser.command_type() if command_type == Parser.C_PUSH or command_type == Parser.C_POP: arg1 = Parser.arg1() arg2 = Parser.arg2() codewriter.writepushpop(command_type, arg1, arg2) elif command_type == Parser.C_ARITHMETIC: command = Parser.arg1() codewriter.writearithmetic(command) elif command_type == Parser.C_LABEL: label = Parser.arg1() codewriter.writelabel(label) elif command_type == Parser.C_GOTO: label = Parser.arg1() codewriter.writegoto(label) elif command_type == Parser.C_IF: label = Parser.arg1() codewriter.writeif(label) elif command_type == Parser.C_FUNCTION: function_name = Parser.arg1() num_locals = Parser.arg2() codewriter.writefunction(function_name, num_locals) elif command_type == Parser.C_CALL: function_name = Parser.arg1() num_args = Parser.arg2() codewriter.writecall(function_name, num_args) elif command_type == Parser.C_RETURN: codewriter.writereturn() Parser.advance() codewriter.close()
def VMTranslator(): inputfile = str(sys.argv[1]) parser = ParserVM(inputfile) coder = CodeWriter(inputfile) coder.setFileName(inputfile) count = 0 while count < len(parser.linelist): parser.advance() if parser.commandType() == 'C_ARITHMETIC': coder.writeArithmetic(parser.arg1()) count += 1 elif parser.commandType() == 'C_PUSH': coder.writePushPop(parser.commandType(), parser.arg1(), parser.arg2()) count += 1 elif parser.commandType() == 'C_POP': coder.writePushPop(parser.commandType(), parser.arg1(), parser.arg2()) count += 1 coder.close()
class Main: def __init__(self, filepath): self.parse_files(filepath) # Initialize CW with a filename, so that # Write init self.cw = CodeWriter(outFile='outFile') self.cw.writeInit() print(f"Files that is to be translated: {self.vm_filenames}") # Note: filename does not include '.vm' for filename in self.vm_filenames: self.translate(filename=filename) self.cw.close() def parse_files(self, filepath): """The filepath can either point to a single file or a folder. If it points to a single file, then self.vm_filenames = [vmFilename] else, if it points to a folder, then self.vm_filenames = [*all_vm_filenames_in_specified_folder*] """ if filepath.endswith('.vm'): # A single .vm file is to be translated vmFile = filepath # eg. 'fibonacci.vm' filename = vmFile.split('.')[0] self.vm_filenames = [filename] return else: # All .vm files in the folder is to be translated if filepath == '/': filepath = os.getcwd() all_files = listdir(filepath) self.vm_filenames = [ file.split('.')[0] for file in all_files if file.endswith('.vm') ] return def translate(self, filename): """!important >>A CodeWriter (cw) instance must be initialized before calling translate<< Given the filename of a single file, translate the vm commands into Hack assembly code and -- using cw -- write the assembly code to an .asm file. The name of the .asm file was specified when initializing the CodeWriter (cw) instance. """ print(f"Currently translating: '{filename}'") parser = Parser(inFile=filename) # Input file is a .vm file self.cw.set_vmFilename(filename=filename) while parser.hasMoreCommands(): curr_cmd = parser.advance() curr_cmdType = parser.commandType(curr_cmd) if curr_cmdType in ('C_PUSH', 'C_POP'): curr_cmdArgs = curr_cmd.split(' ') self.cw.writePushPop(command=curr_cmdType, segment=curr_cmdArgs[1], i=curr_cmdArgs[2]) elif curr_cmdType == 'C_ARITHMETIC': self.cw.writeArithmetic(cmd=curr_cmd) elif curr_cmdType == 'C_LABEL': self.cw.writeLabel(cmd=curr_cmd) elif curr_cmdType == 'C_GOTO': self.cw.writeGoto(cmd=curr_cmd) elif curr_cmdType == 'C_IF': self.cw.writeIfgoto(cmd=curr_cmd) elif curr_cmdType == 'C_FUNCTION': # Eg. 'function SimpleFunction.test 2' curr_cmdArgs = curr_cmd.split(' ') self.cw.writeFunction(functionName=curr_cmdArgs[1], numLocals=int(curr_cmdArgs[2])) elif curr_cmdType == 'C_RETURN': self.cw.writeReturn() elif curr_cmdType == 'C_CALL': # Eg. 'call Bar.mult 2' curr_cmdArgs = curr_cmd.split(' ') self.cw.writeCall(functionName=curr_cmdArgs[1], numArgs=curr_cmdArgs[2]) print('____________') print(curr_cmd) print(curr_cmdType)
try: dirPath = "/".join(argv[1].split("/")) + "/" files = [dirPath + fn for fn in os.listdir(argv[1]) if fn[-3:] == ".vm"] except NotADirectoryError: files = [argv[1]] #それぞれParse, コード生成 for file in files: P = Parser(file) C.setFileName(file) while(P.hasMoreCommands): P.advance() if P.commandType == CommandType.C_ARITHMETIC: C.writeArithmetic(P.arg0) elif P.commandType == CommandType.C_PUSH: C.writePushPop(P.commandType, P.arg0, P.arg1) elif P.commandType == CommandType.C_POP: C.writePushPop(P.commandType, P.arg0, P.arg1) elif P.commandType == CommandType.C_LABEL: C.writeLabel(P.arg0) elif P.commandType == CommandType.C_GOTO: C.writeGoto(P.arg0) elif P.commandType == CommandType.C_IF: C.writeIf(P.arg0) elif P.commandType == CommandType.C_FUNCTION: C.writeFunction(P.arg0, P.arg1) elif P.commandType == CommandType.C_RETURN: C.writeReturn() elif P.commandType == CommandType.C_CALL: C.writeCall(P.arg0, P.arg1) C.close()
command = parser_obj.getCommand() commandType = parser_obj.commandType() out_file_obj.writeCommand(command) if commandType == 'C_RETURN': out_file_obj.writeReturn() elif (commandType == 'C_PUSH') or (commandType == 'C_POP') \ or (commandType == 'C_FUNCTION') or (commandType == 'C_CALL'): arg1 = parser_obj.arg1() arg2 = parser_obj.arg2() if commandType == "C_FUNCTION": out_file_obj.writeFunction(arg1, arg2) elif commandType == "C_CALL": out_file_obj.writeCall(arg1, arg2) else: out_file_obj.writePushPop(command, commandType, arg1, arg2) else: arg1 = parser_obj.arg1() if commandType == "C_LABEL": out_file_obj.writeLabel(arg1) elif commandType == "C_GOTO": out_file_obj.writeGoto(arg1) elif commandType == "C_IF": out_file_obj.writeIf(arg1) elif commandType == 'C_ARITHMETIC': out_file_obj.writeArithmetic(arg1) parser_obj.advance() out_file_obj.close()
writer = CodeWriter(outPath) for f in vmNames: fn = path.basename(f) print "Working on:",fn writer.setFileName(fn) parser = Parser(f) while parser.hasMoreCommands(): parser.advance() if parser.commandType() == "C_ARITHMETIC": writer.writeArithmetic(parser.arg1()) elif parser.commandType() == "C_PUSH": writer.writePushPop("PUSH", parser.arg1(), parser.arg2()) elif parser.commandType() == "C_POP": writer.writePushPop("POP", parser.arg1(), parser.arg2()) elif parser.commandType() == "C_LABEL": writer.writeLabel(parser.arg1()) elif parser.commandType() == "C_GOTO" or parser.commandType() == "C_IF-GOTO": writer.writeGoto(parser.commandType()[2:], parser.arg1()) elif parser.commandType() == "C_FUNCTION": writer.writeFunct(parser.arg1(), parser.arg2()) elif parser.commandType() == "C_CALL": writer.writeCall(parser.arg1(), parser.arg2()) elif parser.commandType() == "C_RETURN": writer.writeReturn() else: print "Command not supported:",parser.commandType() writer.close() print inPath,"=>",outPath
cw.writeComment(parser.command(), parser.lineno()) # Generate the code for the command if ctype == Parser.C_ARITHMETIC: cw.writeArithmetic(arg1, parser.lineno()) elif ctype == Parser.C_PUSH or ctype == Parser.C_POP: cw.writePushPop(ctype, arg1, arg2) elif ctype == Parser.C_LABEL: cw.writeLabel(arg1) elif ctype == Parser.C_GOTO: cw.writeGoto(arg1) elif ctype == Parser.C_IF: cw.writeIf(arg1) elif ctype == Parser.C_FUNCTION: cw.writeFunction(arg1, arg2) elif ctype == Parser.C_RETURN: cw.writeReturn() elif ctype == Parser.C_CALL: cw.writeCall(arg1, arg2) elif ctype in range(len(Parser.CMDS)): print("WARNING: Unimplemented ctype: " + str(ctype)) else: print("ERROR: Unrecognized ctype: " + str(ctype)) sys.exit(1) # Write a blank line into the ASM file after each VM command cw.writeBlank() # Close the CodeWriter cw.close()
class BackEndProject7(object): def __init__(self, vmfile): # project7 不考虑分支命令 和 函数调用命令 # 只考虑单个vm文件 if os.path.isdir(vmfile): return else: f = open(vmfile, 'r') lines = f.readlines() f.close() vm_commands = [] for i in range(len(lines)): line = lines[i].strip() slash_idx = len(line) if '//' in line: slash_idx = line.index('//') line = line[:slash_idx] line= line.rstrip() line = line.split(' ') line = filter(lambda x:x, line) line = ' '.join(line) if line == '': continue if not self.valid(line): raise Exception("invalid vm statement in line {0}".format(i+1)) print "line: ", line vm_commands.append(line) self.parser = Parser() self.parser.coms = vm_commands self.parser.len_coms = len(vm_commands) dirt = os.path.dirname(vmfile) filename = os.path.basename(vmfile) asm_name = filename.split('.')[0] + '.asm' self.asm_name = os.path.join(dirt, asm_name) print '' print "direct: ", dirt print "vmname: ", filename print "asmname: ", asm_name print "fullpath_asm: ", self.asm_name print '' self.codewriter = CodeWriter(self.asm_name) def valid(self, line): return True def complile(self): while self.parser.hasMoreCommands(): vm_com = self.parser.advance() comtype = self.parser.commandType(vm_com) if comtype in ["C_PUSH", "C_POP"]: seg = self.parser.arg1(vm_com, comtype) index = self.parser.arg2(vm_com, comtype) self.codewriter.writePushPop(comtype, seg, index) elif comtype == "C_ARITHMETIC": self.codewriter.writeArithmetic(vm_com) self.codewriter.close()
file_name = check_input() if file_name is not None: # this case handles single file parser = Parser(file_name + DOT + VM_EXTENSION) try: code_writer = CodeWriter(file_name) parse_commands_and_write_output() except IOError: print(FILE_WRITE_ERROR) sys.exit() else: path_name = check_input_folder() if path_name is None: print(USAGE_INSTRUCTION) sys.exit() try: # this case handles a directory file_name = path_name.split(BACK_SLASH)[-1] code_writer = CodeWriter(path_name + BACK_SLASH + file_name) for root, dirs, files in os.walk(path_name): for file_in_folder in files: check_extension = file_in_folder.split(DOT)[-1] if check_extension == VM_EXTENSION: parser = Parser(path_name + BACK_SLASH + file_in_folder) code_writer.set_file_name(file_in_folder.split(DOT)[0]) parse_commands_and_write_output() code_writer.close() except IOError: print(FILE_WRITE_ERROR) sys.exit()
def VMTranslator(): inputArg = str(sys.argv[1]) directory_flag = False if inputArg.endswith('.vm'): #IE single file inputfile = inputArg parser = ParserVM(inputfile) coder = CodeWriter(inputfile) else: #IE directory outputfile_name = inputArg + '.asm' cur_directory = os.getcwd( ) + '/' + inputArg #creates file path for making a list of file in directory directory_flag = True if os.path.exists(cur_directory): # if directory exists, continue os.chdir(cur_directory) #make current working directory file_list = os.listdir( cur_directory) #creates list of file in directory for filename in file_list: if filename.endswith('.vm'): parser = ParserVM(filename) coder = CodeWriter(filename) for i in range(len(parser.linelist)): parser.advance() if parser.commandType() == 'C_ARITHMETIC': coder.writeArithmetic(parser.arg1()) elif parser.commandType() == 'C_PUSH': coder.writePushPop(parser.commandType(), parser.arg1(), parser.arg2()) elif parser.commandType() == 'C_POP': coder.writePushPop(parser.commandType(), parser.arg1(), parser.arg2()) elif parser.commandType() == 'C_LABEL': coder.writeLabel(parser.arg1()) elif parser.commandType() == 'C_GOTO': coder.writeGoto(parser.arg1()) elif parser.commandType() == 'C_IF': coder.writeIf(parser.arg1()) elif parser.commandType() == 'C_FUNCTION': coder.writeFunction(parser.arg1(), parser.arg2()) elif parser.commandType() == 'C_CALL': coder.writeCall(parser.arg1(), parser.arg2()) elif parser.commandType() == 'C_RETURN': coder.writeReturn() else: continue #concatonate file together here new_list = os.listdir( cur_directory) #contains .asm files (hopefully) asm_list = [] for entry in new_list: if entry.endswith('.asm'): asm_list.append(entry) #mainLines=[] else: print('Directory not found') raise (FileNotFoundError) #main code below, only translates one file at a time for i in range(len(parser.linelist)): parser.advance() if parser.commandType() == 'C_ARITHMETIC': coder.writeArithmetic(parser.arg1()) elif parser.commandType() == 'C_PUSH': coder.writePushPop(parser.commandType(), parser.arg1(), parser.arg2()) elif parser.commandType() == 'C_POP': coder.writePushPop(parser.commandType(), parser.arg1(), parser.arg2()) elif parser.commandType() == 'C_LABEL': coder.writeLabel(parser.arg1()) elif parser.commandType() == 'C_GOTO': coder.writeGoto(parser.arg1()) elif parser.commandType() == 'C_IF': coder.writeIf(parser.arg1()) elif parser.commandType() == 'C_FUNCTION': coder.writeFunction(parser.arg1(), parser.arg2()) elif parser.commandType() == 'C_CALL': coder.writeCall(parser.arg1(), parser.arg2()) elif parser.commandType() == 'C_RETURN': coder.writeReturn() coder.close() if directory_flag == True: with open(outputfile_name, 'w') as wfd: #could not get my IO for writeInit working so here it is manually entered wfd.write('@256' + '\n') wfd.write('D=A' + '\n') wfd.write('A=0' + '\n') wfd.write('M=D' + '\n') wfd.write('//call Sys.init 0 ' '\n') wfd.write('@return-address' + '\n') wfd.write('D=A' + '\n') wfd.write('@SP' + '\n') wfd.write('A=M' + '\n') wfd.write('M=D' + '\n') wfd.write('@SP' + '\n') wfd.write('M=M+1' + '\n') #push local //copied from STATIC PUSH ABOVE wfd.write( '//push LCL' + '\n' ) #writes comments in .asm language telling you command given before assembly code is generated wfd.write('@LCL' + '\n') #accesses address of index wfd.write('D=M' + '\n') #sets the address into D reg wfd.write('@SP' + '\n') #gets address if index wfd.write( 'A=M' + '\n') #adds base *sp to index value and puts it into D reg wfd.write('M=D' + '\n') wfd.write('@SP' + '\n') #accesses SP wfd.write('M=M+1' + '\n') #incements value of SP by 1 #push argument wfd.write( '//push ARG' + '\n' ) #writes comments in .asm language telling you command given before assembly code is generated wfd.write('@ARG' + '\n') #accesses address of index wfd.write('D=M' + '\n') #sets the address into D reg wfd.write('@SP' + '\n') #gets address if index wfd.write( 'A=M' + '\n') #adds base *sp to index value and puts it into D reg wfd.write('M=D' + '\n') wfd.write('@SP' + '\n') #accesses SP wfd.write('M=M+1' + '\n') #incements value of SP by 1 #push this wfd.write( '//push THIS' + '\n' ) #writes comments in .asm language telling you command given before assembly code is generated wfd.write('@THIS' + '\n') #accesses address of index wfd.write('D=M' + '\n') #sets the address into D reg wfd.write('@SP' + '\n') #gets address if index wfd.write( 'A=M' + '\n') #adds base *sp to index value and puts it into D reg wfd.write('M=D' + '\n') wfd.write('@SP' + '\n') #accesses SP wfd.write('M=M+1' + '\n') #incements value of SP by 1 #push that wfd.write( '//push THAT' + '\n' ) #writes comments in .asm language telling you command given before assembly code is generated wfd.write('@THAT' + '\n') #accesses address of index wfd.write('D=M' + '\n') #sets the address into D reg wfd.write('@SP' + '\n') #gets address if index wfd.write( 'A=M' + '\n') #adds base *sp to index value and puts it into D reg wfd.write('M=D' + '\n') wfd.write('@SP' + '\n') #accesses SP wfd.write('M=M+1' + '\n') #incements value of SP by 1 #ARG=SP-numArgs-5 wfd.write('@SP' + '\n') wfd.write('D=M' + '\n') #*sp into D reg wfd.write('@0' + '\n') #go to @ num Args reg wfd.write('D=D-A' + '\n') #ie SP-numArgs into D wfd.write('@5' + '\n') wfd.write('D=D-A' + '\n') #ie SP-numArgs-5 into D wfd.write('@ARG' + '\n') wfd.write('M=D' + '\n') #ARG=SP-numArgs-5 #LCL=SP wfd.write('@SP' + '\n') wfd.write('D=M' + '\n') #*sp wfd.write('@LCL' + '\n') wfd.write('M=D' + '\n') #LCL=SP #goto functionName copied from goto wfd.write('@Sys.init' + '\n') wfd.write('0;JMP' + '\n') #(return-address) wfd.write('(return-address)' + '\n') for f in asm_list: print(f) if inputArg in f: continue with open(f, 'r') as fd: shutil.copyfileobj(fd, wfd)
else: CodeW.writeInit() for file in _vm_parser_outputs: for line in file: # print(line) line = line.split(" ") if line[0] == "$$NEW_FILE$$": # changing filename CodeW.set_filename(os.path.basename(line[1])) elif line[0] == "goto" or line[0] == "label" or line[0] == "if-goto": # print("Label "+line) CodeW.write_label(line[0], line[1]) elif line[0] == "function": CodeW.write_function(line[1], line[2]) elif line[0] == "call": CodeW.write_call(line[1], line[2]) elif line[0] == "return": CodeW.write_return() elif line[0] == "push" or line[0] == "pop": # print("PushPop "+line) CodeW.write_push_pop(line[0], line[1], line[2]) else: # print("Arithmetic "+line) CodeW.write_arithmetic(line[0]) CodeW.close()
if len(vm_files) > 1: codewriter.writeInit() for vm_file in vm_files: parser = Parser(vm_file) codewriter.setModuleName(vm_file) while parser.hasMoreCommands(): parser.advance() ctype = parser.commandType() arg1 = parser.arg1() arg2 = parser.arg2() if ctype == "C_ARITHMETIC": codewriter.writeArithmetic(parser.currCommand[0]) elif ctype == "C_PUSH" or ctype == 'C_POP': codewriter.writePushPop(ctype, arg1, arg2) elif ctype == "C_LABEL": codewriter.writeLabel(arg1) elif ctype == "C_GOTO": codewriter.writeGoto(arg1) elif ctype == "C_IF": codewriter.writeIf(arg1) elif ctype == "C_FUNCTION": codewriter.writeFunction(arg1, arg2) elif ctype == "C_CALL": codewriter.writeCall(arg1, arg2) elif ctype == "C_RETURN": codewriter.writeReturn() codewriter.close()
def main(): args = [x for x in sys.argv] if len(args) < 2: raise Exception( "Error[7]: No file/dir name provided \"Usage: python VMTranslator.py file.vm\"" ) if not os.path.isfile(args[1]) and not os.path.isdir(args[1]): raise FileNotFoundError("Error[8]: \"" + args[1] + "\" does not exist") input_files = [os.path.abspath(args[1])] print(input_files) output_file_name = os.path.abspath(args[1]) is_input_dir = False if os.path.isdir(input_files[0]): is_input_dir = True input_files = [f for f in os.listdir(input_files[0])] input_files = [f for f in input_files if f.split(".")[-1] == "vm"] input_files = [os.path.join(output_file_name, f) for f in input_files] output_file_name = os.path.join(output_file_name, os.path.basename(output_file_name)) print(input_files) print(output_file_name) code_writer = CodeWriter(output_file_name) if is_input_dir: code_writer.writeInit() for file_name in input_files: parser = Parser(file_name) code_writer.setFileName(file_name) while parser.hasMoreCommands(): parser.advance() arg1 = None arg2 = None if parser.commandType() != CommandTypes.C_RETURN: arg1 = parser.arg1() if parser.commandType() == CommandTypes.C_PUSH or \ parser.commandType() == CommandTypes.C_POP or \ parser.commandType() == CommandTypes.C_FUNCTION or \ parser.commandType() == CommandTypes.C_CALL: arg2 = parser.arg2() if parser.commandType( ) == CommandTypes.C_ARITHMETIC and arg1 is not None: code_writer.writeArithmetic(arg1) if (parser.commandType() == CommandTypes.C_PUSH or \ parser.commandType() == CommandTypes.C_POP) and \ arg1 is not None and arg2 is not None: code_writer.writePushPop(parser.commandType(), arg1, arg2) if parser.commandType( ) == CommandTypes.C_LABEL and arg1 is not None: code_writer.writeLabel(arg1) if parser.commandType( ) == CommandTypes.C_GOTO and arg1 is not None: code_writer.writeGoto(arg1) if parser.commandType() == CommandTypes.C_IF and arg1 is not None: code_writer.writeIf(arg1) if parser.commandType() == CommandTypes.C_FUNCTION and \ arg1 is not None and arg2 is not None: code_writer.writeFunction(arg1, arg2) if parser.commandType() == CommandTypes.C_CALL and \ arg1 is not None and arg2 is not None: code_writer.writeCall(arg1, arg2) if parser.commandType() == CommandTypes.C_RETURN: code_writer.writeReturn() code_writer.close()
return self.index < len(self.instructions); def advance(self): self.index = self.index + 1; def commandType(self): match = re.match(r'(\w+).*', self.instructions[self.index]); return match.groups()[0]; def arg1(self): match = re.match(r'\w+\s+(\w+).*', self.instructions[self.index]); return match.groups()[0]; def arg2(self): match = re.match(r'\w+\s+\w+\s+(\w+)', self.instructions[self.index]); return match.groups()[0]; if __name__ == '__main__': path = os.path.dirname(sys.argv[1]); filename = os.path.basename(sys.argv[1]); parser = Parser(path + '/' + filename); writer = CodeWriter(path, filename.split('.')[0]); while parser.hasMoreCommands(): command = parser.commandType(); if(command == 'push' or command == 'pop'): writer.writePushPop(command, parser.arg1(), parser.arg2()); else: writer.writeArithmetic(command); parser.advance(); writer.close();