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()
Beispiel #2
0
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())
Beispiel #3
0
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()
Beispiel #4
0
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()
Beispiel #7
0
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()
Beispiel #8
0
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.")
Beispiel #9
0
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()
Beispiel #10
0
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()
Beispiel #12
0
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())
Beispiel #13
0
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()
Beispiel #14
0
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()
Beispiel #15
0
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)
Beispiel #16
0
    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()
Beispiel #17
0
        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()
Beispiel #18
0
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()
Beispiel #21
0

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()
Beispiel #22
0
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)
Beispiel #23
0
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()
Beispiel #24
0
            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()
Beispiel #26
0
		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();