def translate(input_file_path, output_file): parser = Parser(input_file_path) command = parser.next_command() current_function = "no_function" while command: command_type = get_command_type(command) parts = command.split() if command_type == MEMORY_ACCESS: output_file.write( memory_access.translate_command( parts[0], parts[1], parts[2], get_file_name(input_file_path))) elif command_type == ARITHMETIC: output_file.write(arithmetic.translate_command(command)) elif command_type == PROGRAM_FLOW: output_file.write( program_flow.translate_command(parts[0], parts[1], current_function)) elif command_type == FUNCTION: if parts[0] == FUNCTION_DECLARATION: current_function = parts[1] if len(parts) == 3: output_file.write( function.translate_command(parts[0], parts[1], parts[2])) else: output_file.write(function.translate_command(parts[0], "", "")) command = parser.next_command() output_file.write("\n\n")
def translate(input_file_path, output_file): parser = Parser(input_file_path) command = parser.next_command() while command: command_type = get_command_type(command) if command_type == MEMORY_ACCESS: parts = command.split() output_file.write( memory_access.translate_command( parts[0], parts[1], parts[2], get_file_name(input_file_path))) elif command_type == ARITHMETIC: output_file.write(arithmetic.translate_command(command)) command = parser.next_command() output_file.write("\n\n")
def test_parser(self): expected = [ "push constant 17", "push constant 17", "eq", "push constant 17", "push constant 16", "eq", "push constant 16", "push constant 17", "eq", "push constant 892", "push constant 891", "lt", "push constant 891", "push constant 892", "lt", "push constant 891", "push constant 891", "lt", "push constant 32767", "push constant 32766", "gt", "push constant 32766", "push constant 32767", "gt", "push constant 32766", "push constant 32766", "gt", "push constant 57", "push constant 31", "push constant 53", "add", "push constant 112", "sub", "neg", "and", "push constant 82", "or", "not" ] vm_parser = Parser("StackArithmetic/StackTest/StackTest.vm") list = [] command = vm_parser.next_command() while command: list.append(command) command = vm_parser.next_command() self.assertListEqual(expected, list)
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()
def read_file(input_file, code_writer): """ Reads and translates to assembly code a single file """ # Creates a new parser to parse the file. parser = Parser(input_file) # Set the current file name to be input file code_writer.set_file_name(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) # If the command type is C_LABEL parses it to get the label and passes it to the code writer to add to the output file elif command_type == "C_LABEL": label = parser.arg1() code_writer.write_label(label) # If the command type is C_GOTO parses it to get the label and passes it to the code writer to add to the output file elif command_type == "C_GOTO": label = parser.arg1() code_writer.write_goto(label) # If the command type is C_IF parses it to get the label and passes it to the code writer to add to the output file elif command_type == "C_IF": label = parser.arg1() code_writer.write_if(label) elif command_type == "C_CALL": function_name = parser.arg1() num_args = parser.arg2() code_writer.write_call(function_name, num_args) # If the command type is C_RETURN passes it to the code writer to add it to the output file. elif command_type == "C_RETURN": code_writer.write_return() # If the command type is C_FUNCTION parses it to get the function name and number of local variables and passes it to the code writer to add to the output file elif command_type == "C_FUNCTION": function_name = parser.arg1() num_locals = parser.arg2() code_writer.write_function(function_name, num_locals) del parser
else: vmfiles = [ inpath + '/' + f for f in os.listdir(inpath) if f.endswith('.vm') ] outdir = vmfiles[0].rsplit('/', 1)[0] outfilename = outdir.rsplit('/', 1)[-1] outpath = outdir + '/' + outfilename + '.asm' translator = Translator() if len(sys.argv) == 3 and sys.argv[2] == '--init': translator.write_init() for file in vmfiles: filename = file.rsplit('.vm', 1)[0].rsplit('/', 1)[-1] translator.set_filename(filename) with open(file, 'r') as infile: lines = infile.readlines() parser = Parser(lines) while parser.has_more_commands(): cmd = parser.advance() cmd_type = parser.get_cmd_type() translator.translate(cmd_type, cmd) translator.close() with open(outpath, 'w') as outfile: outfile.write(translator.translation)
if '.vm' in file: dirs.append(os.path.join(r, file)) #Si es un archivo .vm lo tomo solito else: dirs = sys.argv del dirs[0] outname = dirs[0].split('.vm')[0] #Creo el codewriter con el nombre del archivo en el cual voy a escribir cw = code_writer(outname) #Si es un directorio escribo el llamado a Sys.init if len(dirs) > 1: cw.writeInit() #Itero sobre cada file for file_path in dirs: #Creo parser y pongo el codewriter con el file que estoy analizando parser = Parser(file_path) cw.setFileName(file_path) # Itero por cada linea while parser.hasMoreCommands(): parser.advance() if parser.commandType() == 'C_PUSH': cw.writePushPop('C_PUSH', parser.arg1(), parser.arg2()) elif parser.commandType() == 'C_POP': cw.writePushPop('C_POP', parser.arg1(), parser.arg2()) elif parser.commandType() == 'C_ARITHMETIC': cw.writeArithmetic(parser.arg1()) elif parser.commandType() == 'C_LABEL': cw.writeLabel(parser.arg1()) elif parser.commandType() == 'C_IF': cw.writeIf(parser.arg1()) elif parser.commandType() == 'C_GOTO':
from vm_parser import Parser, VMCommandType from vm_code_writer import CodeWriter import sys from pathlib import Path if __name__ == '__main__': if len(sys.argv) > 1: program_path = sys.argv[1] parser = Parser(program_path) file_name = Path(program_path).with_suffix('.asm') writer = CodeWriter(file_name) while parser.has_more_commands(): parser.advance() c_type = parser.command_type() if c_type == VMCommandType.C_POP or c_type == VMCommandType.C_PUSH: writer.write_push_pop(c_type, parser.arg1, parser.arg2) elif c_type == VMCommandType.C_ARITHMETIC: writer.write_arithmetic(parser.arg1) writer.close() else: raise TypeError("1 argument is required: program path, 0 arguments entered")
def compile_single(self, vm): pure_vm = Preprocessor().process(vm.read_text()) parsed_vm = Parser().parse(pure_vm) return CodeGenerator(vm.stem).generate(parsed_vm)
program_path = sys.argv[1] if isfile(program_path): files = [program_path] output_path = Path(program_path).parent elif isdir(program_path): files = glob.glob(join(program_path, '*.vm')) output_path = program_path else: raise FileNotFoundError("[Errno 2] No such file or directory: ", program_path) output_file_name = PurePath(program_path).name.split('.')[0] + '.asm' output_file = Path(output_path, output_file_name) writer = CodeWriter(output_file) for i, vm_file in enumerate(files): parser = Parser(vm_file) file_name = PurePath(program_path).name writer.set_file_name(file_name) while parser.has_more_commands(): parser.advance() c_type = parser.command_type() if c_type == VMCommandType.C_POP or c_type == VMCommandType.C_PUSH: writer.write_push_pop(c_type, parser.arg1, parser.arg2) elif c_type == VMCommandType.C_ARITHMETIC: writer.write_arithmetic(parser.arg1) elif c_type == VMCommandType.C_LABEL: writer.write_label(parser.arg1) elif c_type == VMCommandType.C_GOTO: writer.write_goto(parser.arg1) elif c_type == VMCommandType.C_IF: writer.write_if(parser.arg1)
import sys from vm_parser import Parser from vm_code_writer import code_writer #Obtengo el nombre del file file_path = sys.argv[1] #Creo parser y code writer parser = Parser(file_path) cw = code_writer(file_path) #Itero por cada linea while parser.hasMoreCommands(): parser.advance() if parser.commandType() == 'C_PUSH': cw.writePushPop('C_PUSH', parser.arg1(), parser.arg2()) elif parser.commandType() == 'C_POP': cw.writePushPop('C_POP', parser.arg1(), parser.arg2()) elif parser.commandType() == 'C_ARITHMETIC': cw.writeArithmetic(parser.arg1()) cw.close()