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()
def __init__(self, tokenizer, file_path): self.tokenizer = tokenizer self.file_path = file_path self.symbol_table = SymbolTable() self.class_name = "" self.code_writer = CodeWriter(self) self.label_ind = 0
class VM_Translator: def __init__(self, path): self.cw = CodeWriter() self.files = [] if ".vm" in path: self.files.append(path) else: os.chdir(path) for filepath in os.listdir(): self.files.append(filepath) self.asmcode = "" def parseFiles(self): self.parsed = [] for filename in self.files: with open(filename) as vmcode: for line in vmcode.readlines(): self.parsed.append(parser(line, filename)) self.parsed = [ parsed for parsed in self.parsed if not parsed["Type"] == "UNKNOWN" ] def translate(self): for line in self.parsed: if line["Type"] == "C_ARITHMETIC": self.asmcode += self.cw.writeArithmetic(line) elif line["Type"] == "C_PUSH": self.asmcode += self.cw.writePush(line) elif line["Type"] == "C_POP": self.asmcode += self.cw.writePop(line) def write(self, path): with open(path, "w") as f: f.write(self.asmcode)
def test_not(self): code_writer = CodeWriter() cmd = '@SP\nAM=M-1\n' cmd += 'D=!M\n' cmd += '@SP\nA=M\nM=D\n' cmd += '@SP\nM=M+1\n' self.assertEqual(code_writer.get_not(), cmd)
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())
def __init__(self, prodir, WriteInit=True): vmfiles = [] for vf in os.listdir(prodir): if vf[-3:] == ".vm": vmfiles.append(os.path.join(prodir, vf)) assert vmfiles self.parser = [Parser() for vmf in vmfiles] for vmf, parser in zip(vmfiles, self.parser): parser.coms = self.read_vm(vmf) parser.len_coms = len(parser.coms) parser.vmf = os.path.basename(vmf) directory = os.path.dirname(vmfiles[0]) asm_name = os.path.basename(directory) + '.asm' self.asmf = os.path.join(directory, asm_name) print '' print "direct: ", directory print "vmfiles:" for vmf in vmfiles: print "\t", vmf print "asmname: ", asm_name print "asmf: ", self.asmf print '' self.codewriter = CodeWriter(self.asmf) self.WI = WriteInit
def test_pop_that_pointer_symbol(self): code_writer = CodeWriter() i = '1' segment = MemorySegmentType.POINTER cmd = '@SP\nAM=M-1\n' cmd += 'D=M\n@THAT\nM=D\n' self.assertEqual(code_writer.get_pop(segment, i), cmd)
def translateFile(vm_file): parser = Parser() codeWriter = CodeWriter(parser) codeWriter.setCurrentVMFile(os.path.basename(vm_file)) hack_file_name = vm_file[:-3] + ".asm" hack_file = open(hack_file_name, "w+") with open(vm_file) as f: for nextLine in f: if hasNewLine(nextLine): nextLine = nextLine[:-1] nextLine = removeCommentsOnLine(nextLine) if (nextLine == ''): continue print nextLine asm_instructions = codeWriter.assembleVMCommand(nextLine) for i in xrange(0, len(asm_instructions)): asm_instructions[i] = asm_instructions[i] + '\n' hack_file.writelines(asm_instructions) hack_file.close()
def test_push_this_pointer_symbol(self): code_writer = CodeWriter() i = '0' segment = MemorySegmentType.POINTER cmd = '@THIS\nD=M\n@SP\nA=M\nM=D\n' cmd += '@SP\nM=M+1\n' self.assertEqual(code_writer.get_push(segment, i), cmd)
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 __init__(self, input_path): self.input_path = input_path if not os.path.isdir(input_path): self.input_path = os.path.dirname(input_path) self.code_writer = CodeWriter(input_path.replace(".vm", ".asm")) else: ouptut_path = os.path.join(input_path, os.path.basename(input_path) + ".asm") self.code_writer = CodeWriter(ouptut_path)
def __init__(self, input: TextIOBase, output: TextIOBase): self.input = input self.output = output self.tokens = [] self.location = 0 self.writer = CodeWriter(output) self.generate_tokens() self.parse_file()
def __init__(self, vmfilename): """Constructs the Parser and CodeWriter objects to be used in translating the file and supplies them with the appropriate filenames. """ asmfilename = vmfilename.split('.')[0] + '.asm' self.parser = Parser(vmfilename) self.code_writer = CodeWriter(asmfilename)
def compile_jack(jack_file_name): token_file_name = jack_file_name.replace('.jack', 'T.xml') token_file = open(token_file_name, 'w') jack_file = open(jack_file_name, 'r') tokenizer = Tokenizer(jack_file, token_file) vm_file = open(jack_file_name.replace('.jack', '') + '.vm', 'w') code_writer = CodeWriter(tokenizer, vm_file) code_writer.compile_class()
def test_pop_argument(self): code_writer = CodeWriter() i = '5' segment = MemorySegmentType.ARGUMENT segment_pointer = 'ARG' cmd = '@' + i + '\nD=A\n@' + segment_pointer + '\nD=D+M\n@addr\nM=D\n' cmd += '@SP\nAM=M-1\n' cmd += 'D=M\n@addr\nA=M\nM=D\n' self.assertEqual(code_writer.get_pop(segment, i), cmd)
def test_pop_temp(self): code_writer = CodeWriter() i = '2' segment = MemorySegmentType.TEMP start_address = '5' cmd = '@' + start_address + '\nD=A\n@' + i + '\nD=D+A\n@addr\nM=D\n' cmd += '@SP\nAM=M-1\n' cmd += 'D=M\n@addr\nA=M\nM=D\n' self.assertEqual(code_writer.get_pop(segment, i), cmd)
def test_pop_static(self): code_writer = CodeWriter() filename = 'filename1' code_writer.set_current_filename(filename) i = '5' segment = MemorySegmentType.STATIC cmd = '@SP\nAM=M-1\n' cmd += 'D=M\n@' + filename + '.' + i + '\nM=D\n' self.assertEqual(code_writer.get_pop(segment, i), cmd)
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 __init__(self, path): self.path = path.replace('\\', '/') try: self.filename = self.path[len(self.path) - self.path[::-1].index('/'):-3] except ValueError: self.filename = self.path[:-3] self.cw = CodeWriter(self.filename) self.parser = Parser(path)
def test_push_local(self): code_writer = CodeWriter() i = '5' segment = MemorySegmentType.LOCAL segment_pointer = 'LCL' cmd = '@' + i + '\nD=A\n@' + segment_pointer + '\nA=M+D\nD=M\n' cmd += '@SP\nA=M\nM=D\n' cmd += '@SP\nM=M+1\n' self.assertEqual(code_writer.get_push(segment, i), cmd)
def run(): with ExitStack() as exit_stack: filename = filepath.split("/")[-1:][0].rstrip(".vm") input_file: IO = exit_stack.enter_context(open(filepath)) output_file: IO = exit_stack.enter_context( open(filepath.rstrip("vm") + "asm", "w")) code_writer = CodeWriter(filename, output_file) for command_type, arg1, arg2 in parse_commands(input_file): code_writer.write_command(command_type, arg1, arg2)
def __init__(self, path): self.cw = CodeWriter() self.files = [] if ".vm" in path: self.files.append(path) else: os.chdir(path) for filepath in os.listdir(): self.files.append(filepath) self.asmcode = ""
class VM_Translator: def __init__(self, path): self.cw = CodeWriter() self.files = [] self.dir = False if ".vm" in path: self.files.append(path) else: self.dir = True os.chdir(path) for filepath in os.listdir(): self.files.append(filepath) self.asmcode = "" def parseFiles(self): self.parsed = [] for filename in self.files: with open(filename) as vmcode: for line in vmcode.readlines(): self.parsed.append(parser(line, filename[:-3])) self.parsed = [ parsed for parsed in self.parsed if not parsed["Type"] == "UNKNOWN" ] def translate(self): # initialize with Sys.init if self.dir: self.asmcode += self.cw.boostrap() for line in self.parsed: if line["Type"] == "C_ARITHMETIC": self.asmcode += self.cw.writeArithmetic(line) elif line["Type"] == "C_PUSH": self.asmcode += self.cw.writePush(line) elif line["Type"] == "C_POP": self.asmcode += self.cw.writePop(line) elif line["Type"] == "C_LABEL": self.asmcode += self.cw.writeLabel(line) elif line["Type"] == "C_GOTO": self.asmcode += self.cw.writeGoto(line) elif line["Type"] == "C_IF": self.asmcode += self.cw.writeIfGoto(line) elif line["Type"] == "C_FUNCTION": self.asmcode += self.cw.writeFuncDef(line) elif line["Type"] == "C_CALL": self.asmcode += self.cw.writeFuncCall(line) elif line["Type"] == "C_RETURN": self.asmcode += self.cw.writeReturn(line) else: self.asmcode += "" def write(self, path): with open(path, "w") as f: f.write(self.asmcode)
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()
def get_correct_lines(self, command_type, line): lines = list() # project 7 part - if command_type == CommandType.C_ARITHMETIC: lines = CodeWriter.arithmetic_line(str(self.label_counter), line) elif command_type == CommandType.C_PUSH: lines = CodeWriter.push_line(str(self.file_name), line) elif command_type == CommandType.C_POP: lines = CodeWriter.pop_line(str(self.file_name), line) # project 8 part - elif command_type == CommandType.C_LABEL: # ( functionName $ labelName ) lines = CodeWriter.label_line(str(self.last_function), line) elif command_type == CommandType.C_GOTO: # ( functionName $ labelName ) lines = CodeWriter.goto_line(str(self.last_function), line) elif command_type == CommandType.C_IF: # ( functionName $ labelName ) lines = CodeWriter.if_line(str(self.last_function), line) elif command_type == CommandType.C_FUNCTION: lines = CodeWriter.function_line(line) elif command_type == CommandType.C_RETURN: lines = CodeWriter.return_line() elif command_type == CommandType.C_CALL: # building return address # which is FILE_NAME$ret.(SOME COUNTER FOR RETURNS) return_address = self.file_name + "$" + "ret." + str( self.label_counter) self.label_counter = self.label_counter + 1 lines = CodeWriter.call_line(return_address, line) return lines
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 test_return(self): code_writer = CodeWriter() cmd = '@LCL\nD=M\n@endFrame\nM=D\n@5\nA=D-A\nD=M\n@retAddr\nM=D\n' cmd += '@SP\nAM=M-1\nD=M\n@ARG\nA=M\nM=D\n' cmd += '@ARG\nD=M+1\n@SP\nM=D\n' cmd += '@endFrame\nD=M\n@1\nA=D-A\nD=M\n@THAT\nM=D\n' cmd += '@endFrame\nD=M\n@2\nA=D-A\nD=M\n@THIS\nM=D\n' cmd += '@endFrame\nD=M\n@3\nA=D-A\nD=M\n@ARG\nM=D\n' cmd += '@endFrame\nD=M\n@4\nA=D-A\nD=M\n@LCL\nM=D\n' cmd += '@retAddr\nA=M\n0;JMP\n' self.assertEqual(code_writer.get_return(), cmd)
def test_push_const(self): code_writer = CodeWriter() i = '5' segment = MemorySegmentType.CONSTANT cmd = '@' + i + '\n' cmd += 'D=A\n' cmd += '@SP\n' cmd += 'A=M\n' cmd += 'M=D\n' cmd += '@SP\n' cmd += 'M=M+1\n' self.assertEqual(code_writer.get_push(segment, i), cmd)
class VMTranslator: def __init__(self): self.parser = VMParser() self.coder = CodeWriter() self.myPath = Path(sys.argv[1]) self.initParameters() def initParameters(self): self.filelists = list() if self.myPath.is_file(): self.filelists = [self.myPath] self.outputFile = str(self.myPath.with_suffix('.asm')) elif self.myPath.is_dir(): self.filelists = [ file for file in self.myPath.iterdir() if str(file).endswith('.vm') ] self.outputFile = str( self.myPath) + ('/' + str(self.myPath.stem) + '.asm') self.outputFileHandle = open(self.outputFile, 'w') def run(self): self.outputFileHandle.write( self.coder.translateCode(['bootstrap'], 'Call Sys.init 0')) for file in self.filelists: fileHandle = open(str(file)) filename = file.stem #extract filename without the extendion e.g foo.vm => foo self.coder.setFilename(filename) for line in fileHandle: sanitizedLine = self.sanitizeInput(line) if len(sanitizedLine) == 0: continue parsedInstruction = self.parser.parse(sanitizedLine) codeString = self.coder.translateCode(parsedInstruction, sanitizedLine) self.outputFileHandle.write(codeString) fileHandle.close() print('Translated VM code to assembly successfully.') # noinspection PyUnboundLocalVariable self.outputFileHandle.close() # remove whitespace and comments from input[line] def sanitizeInput(self, line): if len(line) == 0 or line.startswith('//'): return '' line = line.strip() commentIndex = line.find('//') if commentIndex > -1: line = line[:commentIndex] return line
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 main(filepath): out_filename, filenames = parseFilePath(filepath) if os.path.exists(out_filename): os.remove(out_filename) if os.path.isfile(filepath): with open(filepath, "r") as infile: data = infile.readlines() parser = Parser(data) code_writer = CodeWriter(out_filename, filenames[0]) writeFile(parser, code_writer) elif os.path.isdir(filepath): for filename in filenames: full_path = os.path.join(filepath, filename + ".vm") with open(full_path, "r") as infile: data = infile.readlines() parser = Parser(data) code_writer = CodeWriter(out_filename, filename) if filenames[0] == filename: code_writer.writeComment("call Sys.init 0") code_writer.writeInit() writeFile(parser, code_writer)
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 __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 main(): input_file = parse_arguments() if validate(input_file): if Path(input_file).is_dir(): files = get_files_from_directory(input_file) code_writer = CodeWriter(input_file) for file in files: lines = read_file(f'{input_file}/{file}') for line in lines: handle_file_output(line, code_writer) else: lines = read_file(input_file) code_writer = CodeWriter(input_file) for line in lines: handle_file_output(line, code_writer)
def test_function(self): code_writer = CodeWriter() f_name = 'file.foo' num_vars = 3 cmd = '(' + f_name + ')\n' i = '0' push_cmd = '@' + i + '\n' push_cmd += 'D=A\n' push_cmd += '@SP\n' push_cmd += 'A=M\n' push_cmd += 'M=D\n' push_cmd += '@SP\n' push_cmd += 'M=M+1\n' cmd += push_cmd * num_vars self.assertEqual(code_writer.get_function(f_name, num_vars), cmd)
def test_call(self): code_writer = CodeWriter() f_name = 'fun' n_args = '3' ret_addr = f_name + '$ret.1' cmd = '@' + ret_addr + '\nD=A\n@SP\nA=M\nM=D\n@SP\nM=M+1\n' cmd += '@LCL\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n' cmd += '@ARG\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n' cmd += '@THIS\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n' cmd += '@THAT\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n' cmd += '@SP\nD=M\n@5\nD=D-A\n@' + n_args + '\nD=D-A\n@ARG\nM=D\n' cmd += '@SP\nD=M\n@LCL\nM=D\n' cmd += '@' + f_name + '\n0;JMP\n' cmd += '(' + ret_addr + ')\n' self.assertEqual(code_writer.get_call(f_name, n_args), cmd)
def main(): "output file setup" filename = sys.argv[1] output = CodeWriter( filename ) "input file setup" input = Parser( ) commandlines = input.commandLines( filename ) for line in commandlines: if input.typeCommand( line ) == 'C_ARITHMETIC': output.writeArithmetic( line ) output.Write() elif input.typeCommand( line ) in [ 'C_PUSH', 'C_POP' ]: output.writePushPop( line ) output.Write() output.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 __init__(self, input_file_path): self.input_file_path = input_file_path self.code_writer = CodeWriter(input_file_path.replace(".vm", ".asm"))
def main(args): ''' You can set vm_file_path to be either a folder (and then an asm file with the folder source_file will be created in the folder) or set it to be a vm file (and then an asm file with the file source_file will be created in the same location) ''' if len(args) != 1: print "Usage: (python) Main.py [<.vm file path>|<source dir path>]" return vm_file_path = args[0] # vm_file_path = "Input/StackArithmetic/SimpleAdd/SimpleAdd.vm" # vm_file_path = "Input/StackArithmetic/StackTest/StackTest.vm" # vm_file_path = "Input/MemoryAccess/BasicTest/BasicTest.vm" # vm_file_path = "Input/MemoryAccess/PointerTest/PointerTest.vm" # vm_file_path = "Input/MemoryAccess/StaticTest/StaticTest.vm" # vm_file_path = "Input/ProgramFlow/BasicLoop/BasicLoop.vm" # vm_file_path = "Input/ProgramFlow/FibonacciSeries/FibonacciSeries.vm" # vm_file_path = "Input/FunctionCalls/SimpleFunction/SimpleFunction.vm" init_code_required = False source_file_paths = [] sep = '/' if '/' in vm_file_path else os.sep if not vm_file_path.endswith(".vm"): source_file_names = [file_name for file_name in os.listdir(vm_file_path) if file_name.endswith('.vm')] source_file_paths += [os.path.join(vm_file_path, file_name) for file_name in source_file_names] init_code_required = 'Sys.vm' in source_file_names asm_file_name = "{0}.asm".format(vm_file_path.split(sep)[-2]) asm_file_path = os.path.join(vm_file_path, asm_file_name) else: source_file_paths = [vm_file_path] asm_file_path = vm_file_path.replace(".vm", ".asm") cw = CodeWriter(asm_file_path) if init_code_required: cw.writeInit() cw.writeFinishLoop() for source_file in source_file_paths: cw.setFileName(source_file) p = Parser(source_file) while(p.hasMoreCommands()): cmdType = p.commandType() if(cmdType == CommandType.C_ARITHMETIC): cw.writeArithmetic(p.arg1()) elif(cmdType == CommandType.C_PUSH or cmdType == CommandType.C_POP): cw.writePushPop(cmdType, p.arg1(), p.arg2()) elif(cmdType == CommandType.C_LABEL): cw.writeLabel(p.arg1()) elif(cmdType == CommandType.C_GOTO): cw.writeGoto(p.arg1()) elif(cmdType == CommandType.C_IF): cw.writeIf(p.arg1()) elif(cmdType == CommandType.C_CALL): cw.writeCall(p.arg1(), p.arg2()) elif(cmdType == CommandType.C_FUNCTION): cw.writeFunction(p.arg1(), p.arg2()) elif(cmdType == CommandType.C_RETURN): cw.writeReturn() p.advance() cw.Close()
inFile.close() #open output file, fail nicely if it fails try: outFile = open(outPath, "w") except: print outPath + ": file could not be opened" exit(1) finally: outFile.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":
inFile.close() #open output file, fail nicely if it fails try: outFile = open(outPath, "w") except: print outPath + ": file could not be opened" exit(1) finally: outFile.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()) if parser.commandType() == "C_PUSH": writer.writePushPop("PUSH", parser.arg1(), parser.arg2()) if parser.commandType() == "C_POP": writer.writePushPop("POP", parser.arg1(), parser.arg2())
def hasMoreCommands(self): 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();
#Author: Josh Wretlind #Class: CSCI 410 - Elements of Computing Systems #Project: ECS 07 - VM Part #1 #Date: 03/03/13 import sys,string,os from Parse import Parser from CodeWriter import CodeWriter infile = sys.argv[1] # Sys.argv is the system argument list object outfile = infile.replace(".vm",".asm") parse = Parser(infile) cw = CodeWriter() while parse.hasMoreCommands(): parse.advance() parse.output() arg1 = "" arg2 = "" print parse.parsedline if(parse.commandType() == parse.C_ERROR): print "Oops, there was an error" break elif(parse.commandType() != parse.C_RETURN): arg1 = parse.arg1() if(parse.commandType() == parse.C_PUSH or parse.commandType() == parse.C_POP or parse.commandType() == parse.C_FUNCTION or parse.commandType() == parse.C_CALL): arg2 = parse.arg2() cw.write(parse.parsedline, parse) output = open(outfile, 'w')
def main(): "output file setup" arg_length = len( sys.argv ) - 2 if arg_length == 0: objectFileName = sys.argv[1].split('.')[0] filename = sys.argv[1] output = CodeWriter(objectFileName, filename) input = Parser( ) commandlines = input.commandLines( filename ) for line in commandlines: if input.typeCommand( line ) == 'C_ARITHMETIC': output.writeArithmetic( line ) output.Write() elif input.typeCommand( line ) in [ 'C_PUSH', 'C_POP' ]: output.writePushPop( line ) output.Write() elif input.typeCommand( line ) == 'C_LABEL': output.writeLabel( line ) output.Write() elif input.typeCommand( line ) == 'C_GOTO': output.writeGoto( line ) output.Write() elif input.typeCommand( line ) == 'C_IFGOTO': output.writeIfGoTo( line ) output.Write() elif input.typeCommand( line ) == 'C_FUNCTION': #output.writeInit( line ) output.writeFunction( line ) output.Write() elif input.typeCommand( line ) == 'C_RETURN': output.writeReturn( line ) output.Write() elif input.typeCommand( line ) == 'C_CALL': output.writeCall( line ) output.Write() else: count = 0 objectFileName = sys.argv[-1] while count < arg_length: "input file setup" filename = sys.argv[ count + 1 ] output = CodeWriter(objectFileName, filename) input = Parser( ) commandlines = input.commandLines( filename ) for line in commandlines: if input.typeCommand( line ) == 'C_ARITHMETIC': output.writeArithmetic( line ) output.Write() elif input.typeCommand( line ) in [ 'C_PUSH', 'C_POP' ]: output.writePushPop( line ) output.Write() elif input.typeCommand( line ) == 'C_LABEL': output.writeLabel( line ) output.Write() elif input.typeCommand( line ) == 'C_GOTO': output.writeGoto( line ) output.Write() elif input.typeCommand( line ) == 'C_IFGOTO': output.writeIfGoTo( line ) output.Write() elif input.typeCommand( line ) == 'C_FUNCTION': #output.writeInit( line ) output.writeFunction( line ) output.Write() elif input.typeCommand( line ) == 'C_RETURN': output.writeReturn( line ) output.Write() elif input.typeCommand( line ) == 'C_CALL': output.writeCall( line ) output.Write() count += 1 output.Close()
args = argument_parser.parse_args() if isdir(args.source): source = args.source.rstrip("/") filenames = glob(join(source, "*.vm")) output_filename = join(source, splitext(basename(source))[0] + ".asm") else: filenames = [args.source] output_filename = split(args.source)[0] + ".asm" if args.stdout: output_file = sys.stdout else: output_file = open(output_filename, "w") cw = CodeWriter(output_file, args.stamp) if args.bootstrap: cw.writeInit() for filename in filenames: cw.setFileName(filename) p = VMParser(filename) while p.hasMoreCommands(): t = p.commandType() if t in ["C_PUSH", "C_POP"]: cw.WritePushPop(t, p.arg1(), p.arg2()) elif t == "C_ARITHMETIC": cw.writeArithmetic(p.arg1()) elif t == "C_LABEL": cw.writeLabel(p.arg1())
elif ctype == 'C_RETURN': codeWriter.writeReturn() elif ctype == 'C_CALL': arg1 = parser.arg1().strip() arg2 = parser.arg2().strip() codeWriter.writeCall(arg1,arg2) parser.advance() parser.rfile.close() filename = sys.argv[1] if os.path.isfile(filename): parser = Parser(filename) codeWriter = CodeWriter() codeWriter.setFileName(filename) codeWriter.wfile.write('@256\nD=A\n@SP\nM=D\n') Main(parser,codeWriter,filename) elif os.path.isfile('Sys.vm'): codeWriter = CodeWriter() codeWriter.setFileName(filename) codeWriter.wfile.write('@256\nD=A\n@SP\nM=D\n') codeWriter.wfile.write('@return_address0\nD=A\n@SP\nA=M\nM=D\n@SP\nM=M+1\ \n@LCL\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n@ARG\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\ \n@THIS\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n@THAT\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\ \n@0\nD=A\n@5\nD=D+A\n@SP\nD=M-D\n@ARG\nM=D\n@SP\nD=M\n@LCL\nM=D\ \[email protected]\n0;JMP\n(return_address0)\n') filelist = os.listdir(os.getcwd()) for item in filelist: if item.endswith('.vm'):