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 main(): if sys.argv[1][-2:] != "vm": print("Error: wrong file type for input, use \".vm\" file !") sys.exit() inputfile = sys.argv[1] #inputfile = "BasicTest.vm" outputfile = inputfile[:-2] + "asm" par = Parse(inputfile) cw = CodeWriter(outputfile) while par.hasMoreCommands(): par.advance() ctype = par.cmdType() #print(par.current_cmd) #print(par.cmdType()) #print(par.arg1()) #print(par.arg2()) if ctype == "C_ARITHMETIC": cw.writeArithmetic(par.arg1()) elif ctype == "C_PUSH" or ctype == "C_POP": cw.writePushPop(ctype, par.arg1(), par.arg2()) cw.close()
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()
def __init__(self, vm_file): self.filename = vm_file self.basename = os.path.splitext(os.path.basename(vm_file))[0] self.writer = CodeWriter(self.basename) self.directory = os.path.dirname(vm_file) self.suffix = '.asm' self.abspath = os.path.abspath(self.filename)
def __init__(self, filenames): self.asm_commands_list = [] file_basenames = set( [os.path.splitext(os.path.basename(f))[0] for f in filenames]) if 'Sys' in file_basenames: self.write_init() for f in filenames: file_data = (line for line in read_file(f)) writer = CodeWriter(f) command = self.advance(file_data) while command: parsed_elements = self.parse(command) if parsed_elements: self.asm_commands_list.append( writer.compose(parsed_elements)) command = self.advance(file_data)
def add_bootstrap_code(asmfile, filename): """Provide the bootstrap code in assembly""" global_variables.function_list.append('Sys') # Open assembly file to receive init code assembly_file = open(asmfile, 'a') # Get basename of the file in provided filepath input_file_basename = os.path.basename(filename) code_writer = CodeWriter(input_file_basename) bootstrap_code = code_writer.write_init() assembly_file.write(bootstrap_code) assembly_file.close()
def get_code_writer(output_file_name): try: code_writer = CodeWriter(output_file_name) except IOError: print("Cannot create an output asm file.") sys.exit(3) return code_writer
def translate(self): codewriter = CodeWriter(path) if os.path.isdir(path): os.chdir(path) for vm_file in os.listdir('.'): if os.path.splitext(vm_file)[1] == '.vm': print(vm_file) self.translate_single_file(vm_file, codewriter) else: self.translate_single_file(path, codewriter)
def main(): p=Path(sys.argv[1]) ctabel = CmdTable() out_filename= p.stem inputfile_list = {} if p.is_file(): outputfile = str(p.parent / (out_filename + ".asm")) inputfile_list[str(p)] = p.stem elif p.is_dir(): outputfile = p / (out_filename + ".asm") for pfile in p.glob('*.vm'): inputfile_list[str(pfile)] = pfile.stem fout = open(outputfile, mode='w') cw = CodeWriter(fout, ctabel) if p.is_dir(): cw.writeBoot() for inf, infname in inputfile_list.items(): write_vm1(inf, infname, ctabel, cw) fout.close()
def main(): if len(sys.argv) < 2: print(u"使い方: %s FILENAME" % sys.argv[0]) sys.exit(1) path = sys.argv[1] if path.endswith(".vm"): #file with CodeWriter(path[:-3] + ".asm") as c: translate_file(path, c) print("Translated to " + path[:-3] + ".asm") else: #dir if path.endswith("/"): path = path[:-1] # glob.glob (PATHを再帰的に取得) files = glob.glob("%s/*" % path) for f in files: if f.endswith(".vm"): print(f) with CodeWriter(f[:-3] + ".asm") as c: translate_file(f, c) print("Translated to" + path + ".asm")
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()
else: return 0 if __name__ == "__main__": path, flag = sys.argv[1], int( sys.argv[2] ), # dir name existing .vm file, wheather exist many file(1) or not(0) allasm_code = [] if flag == 0: f_list = list(map(lambda x: path + '/' + x, os.listdir(path))) file = [f for f in f_list if re.search('.vm', f) != None][0][:-3] init_flag = get_init_flag(file) codewriter = CodeWriter(file, init_flag) parser = Parser(file) allasm_code += vm2asm_translater(codewriter, parser) else: old_return_addr = 0 old_labelNum = 0 init_flag = 1 f_list = list(map(lambda x: path + '/' + x, os.listdir(path))) for f in f_list: if re.search('.*\.vm', f) != None: file = re.sub('\.vm', '', f) codewriter = CodeWriter(file, init_flag) parser = Parser(file) codewriter.labelNum = old_labelNum codewriter.return_address = old_return_addr allasm_code += vm2asm_translater(codewriter, parser)
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()
from parser import Parser from codewriter import CodeWriter import sys import re if __name__ == "__main__": path = sys.argv[1] codewriter = CodeWriter(path) parser = Parser(path) while parser.hasMoreCommands(): parser.advance() print(parser.current_cmd) cmdtype = parser.commandType() arg1 = parser.arg1() if cmdtype == 'C_ARITHMETIC': codewriter.writeArithmetic(arg1) elif cmdtype in ['C_PUSH', 'C_POP']: arg2 = parser.arg2() codewriter.wirtePushPop(cmdtype, arg1, arg2) codewriter.fileToOutput()
def __init__(self): self.codewriter = CodeWriter()
pop_type='C_POP' lable_type='C_LABEL' goto_type='C_GOTO' if_type='C_IF' funct_type='C_FUNCTION' ret_type='C_RETURN' call_type='C_CALL' in_file='' out_file='' #for directories directory = [] is_dir=False writer = CodeWriter() #------------------------------------------------------------------------------ # Check user input #------------------------------------------------------------------------------ if len(sys.argv) < 1: #Checks to see if user put in file print('incorrect number of args!') print('assembler.py <file.vm|directry path>') sys.exit(0) in_file=sys.argv[1] #Checks for correct file name if not then assumes directory if re.search('.*\.vm',in_file) is None: is_dir=True #goes through the directory and finds the .vm files
else: #Strips .vm of the end and adds .asm temp_out=re.search('(.*)(\.vm)',in_file) out_file+=temp_out.group(1)+'.asm' #------------------------------------------------------------------------------ # Main #------------------------------------------------------------------------------ #For directories passed in if is_dir: cur_dir = os.getcwd() temp_dir = re.search('([\/"\\"]{1})([A-Za-z0-9\.\_\-\s]*$)',cur_dir) fileName = temp_dir.group(2)+'.asm' #opens the file named after the directory with .asm appended writer = CodeWriter(cur_dir+'/'+fileName) writer.writeInit() for d in directory: #Strips .vm of the end to get the file name temp_out=re.search('(.*[\.\/]+)(.*)(\.vm)',d) out_file = temp_out.group(2) #sets current file name writer.setFileName(out_file) #opens the input file par = Parser(d) #while not eof while par.hasMoreCommands(): par.advance() cType = par.commandType()
class CodeGenerator(): def __init__(self): self.codewriter = CodeWriter() def codegen(self, ast): """Entry point into codeGenerator.Starts the recursive compilation and returns the final result to calling function""" self.class_({},ast.next_sec()) return self.codewriter.get_code() def class_(self, state, ast): """Create class symbol table and pass on control to classVarDec and subroutineDec. No code geneartion here""" ast.next() #'class keyword' state['classname'] = ast.next_val() ast.next() #'{' state['sym_tbl'] = SymbolTable() while(ast.get_key() == 'classVarDec'): self.classVarDec(state, ast.next_sec()) while(ast.get_key() == 'subroutineDec'): self.subroutineDec(state, ast.next_sec()) ast.next() #'}' return def classVarDec(self, state, ast): """Parse static and field and add to symbol table""" var_kind = ast.next_val() var_type = ast.next_val() var_name = ast.next_val() state['sym_tbl'].add(var_name, var_kind, var_type) while(ast.next_val() != ';'): var_name = ast.next_val() state['sym_tbl'].add(var_name, var_kind, var_type) return def subroutineDec(self, state, ast): statelocal = state.copy() #we keep a local frame for each function statelocal['sym_tbl'] = SymbolTable(state['sym_tbl']) statelocal['fkind'] = ast.next_val() #constructor, function, method statelocal['fype']= ast.next_val() #return type statelocal['fname'] = ast.next_val() #function name statelocal['cf_count'] = 0 #control flow labels #new symbol table with parent linkage if statelocal['fkind'] == 'method': statelocal['sym_tbl'].var_counter['argument'] += 1 ast.next() #'(' self.parameterList(statelocal,ast.next_sec()) ast.next() #')' self.subroutineBody(statelocal, ast.next_sec()) return def parameterList(self, state, ast): if(ast.get_val() is not None): var_type = ast.next_val() var_name = ast.next_val() state['sym_tbl'].add(var_name, 'argument', var_type) while(ast.get_val() == ','): ast.next() var_type = ast.next_val() var_name = ast.next_val() state['sym_tbl'].add(var_name, 'argument', var_type) return def subroutineBody(self, state, ast): ast.next() # '{' while(ast.get_key() == 'varDec'): self.varDec(state, ast.next_sec()) self.codewriter.function(state) self.statements(state, ast.next_sec()) ast.next() # '}' return def varDec(self, state, ast): ast.next() #'var' var_type = ast.next_val() var_name = ast.next_val() state['sym_tbl'].add(var_name, 'local', var_type) while(ast.next_val() != ';'): var_name = ast.next_val() state['sym_tbl'].add(var_name, 'local', var_type) return def statements(self, state, ast): xstatements = { 'returnStatement':self.returnStatement, 'ifStatement':self.ifStatement, 'letStatement':self.letStatement, 'whileStatement':self.whileStatement, 'doStatement':self.doStatement } xstatement = ast.get_key() while(xstatement is not None): xstatements[xstatement](state, ast.next_sec()) xstatement = ast.get_key() return def doStatement(self, state, ast): ast.next() #'do' self.subroutineCall(state,ast.next_sec()) self.codewriter.pop('temp', 0) #throw away void return ast.next() #';' return def returnStatement(self, state, ast): ast.next() #'return' if ast.get_key() == 'expression': self.expression(state, ast.next_sec()) else: self.codewriter.push('constant', 0) self.codewriter.raw('return') ast.next() #';' return def ifStatement(self, state, ast): cf_count = state['cf_count'] state['cf_count'] += 1 ast.next() # 'if' ast.next() # '(' self.expression(state, ast.next_sec()) ast.next() # ')' self.codewriter.if_goto('IF_TRUE',cf_count) self.codewriter.goto('IF_FALSE',cf_count) ast.next() # '{' self.codewriter.label('IF_TRUE', cf_count) self.statements(state, ast.next_sec()) ast.next() # '}' if(ast.get_val() == 'else'): self.codewriter.goto('IF_END',cf_count) self.codewriter.label('IF_FALSE', cf_count) if(ast.get_val() == 'else'): ast.next() # 'else' ast.next() # '{' self.statements(state, ast.next_sec()) ast.next() # '}' self.codewriter.label('IF_END', cf_count) return self.codewriter.label('IF_FALSE', cf_count) return def whileStatement(self, state, ast): cf_count = state['cf_count'] state['cf_count'] += 1 self.codewriter.label('WHILE_EXP', cf_count) ast.next() # 'while' ast.next() # '(' self.expression(state, ast.next_sec()) ast.next() # ')' self.codewriter.raw('not') self.codewriter.if_goto('WHILE_END',cf_count) ast.next() # '{' self.statements(state, ast.next_sec()) ast.next() # '}' self.codewriter.goto('WHILE_EXP', cf_count) self.codewriter.label('WHILE_END', cf_count) return def letStatement(self, state, ast): ast.next() # 'let' varname = ast.next_val() if ast.get_val() == '[': ast.next() # '[' self.expression(state, ast.next_sec()) self.codewriter.push_var(state['sym_tbl'].lookup(varname)) self.codewriter.raw('add') ast.next() # ']' ast.next() # '=' self.expression(state, ast.next_sec()) self.codewriter.pop('temp', 0) self.codewriter.pop('pointer', 1) self.codewriter.push('temp', 0) self.codewriter.pop('that', 0) else: ast.next() # '=' self.expression(state, ast.next_sec()) self.codewriter.pop_var(state['sym_tbl'].lookup(varname)) ast.next() # ';' return def subroutineCall(self, state, ast): if state['sym_tbl'].lookup(ast.get_val()) is not None: #other class method call objname = ast.next_val() obj = state['sym_tbl'].lookup(objname) ast.next() # dot fname = ast.next_val() self.codewriter.push_var(obj) #push object as first argument ast.next() # '(' argc = self.expressionList(state, ast.next_sec()) #push other arguments #argc is number of "actual" arguments ast.next() # ')' self.codewriter.call(obj.type, fname, argc+1) else: #not other class method call firstname = ast.next_val() if ast.get_val() == '.': #Class.function() classname = firstname ast.next() fname = ast.next_val() ast.next() # '(' argc = self.expressionList(state, ast.next_sec()) #push other arguments #argc is number of "actual" arguments ast.next() # ')' self.codewriter.call(classname, fname, argc) else: #self method call classname = state['classname'] #own class name fname = firstname self.codewriter.push('pointer', 0) #push this as first argument ast.next() # '(' argc = self.expressionList(state, ast.next_sec()) #push other arguments ast.next() # ')' self.codewriter.call(classname, fname, argc+1) return def expressionList(self, state, ast): argc = 0 if ast.get() is not None: self.expression(state, ast.next_sec()) argc += 1 while(ast.get_val() is not None): ast.next() self.expression(state, ast.next_sec()) argc += 1 return argc def expression(self, state, ast): ops = { '+': 'add', '-': 'sub', '*': 'call Math.multiply 2', '/': 'call Math.divide 2', '|': 'or', '&' : 'and', '=': 'eq', '<' : 'lt', '>' : 'gt' } self.term(state, ast.next_sec()) while(ast.get_val() is not None): op = ast.next_val() self.term(state, ast.next_sec()) self.codewriter.raw(ops[op]) return def term(self, state, ast): key = ast.get_key() if key == 'integerConstant': self.codewriter.push('constant', ast.next_val()) elif key == 'stringConstant': self.codewriter.string(ast.next_val()) elif key == 'keyword': val = ast.next_val() if val == 'true': self.codewriter.raw('push constant 0\nnot') elif val == 'false': self.codewriter.raw('push constant 0') elif val == 'null': self.codewriter.raw('push constant 0') elif val == 'this': self.codewriter.push_this() elif key == 'arrayAccess': nast = ast.next_sec() varname = nast.next_val() nast.next() # '[' self.expression(state, nast.next_sec()) nast.next() # ']' self.codewriter.push_var(state['sym_tbl'].lookup(varname)) self.codewriter.raw('add') #base address + index self.codewriter.pop('pointer', 1) #store indexed address in 'that' self.codewriter.push('that', 0) elif key == 'subroutineCall': self.subroutineCall(state, ast.next_sec()) elif key == 'bracketExp': nast = ast.next_sec() nast.next() #'(' self.expression(state, nast.next_sec()) nast.next() #')' elif key == 'unaryOpTerm': nast = ast.next_sec() op = nast.next_val() self.term(state, nast.next_sec()) if op == '-': self.codewriter.raw('neg') if op == '~': self.codewriter.raw('not') elif key == 'identifier': self.codewriter.push_var(state['sym_tbl'].lookup(ast.next_val()))