Beispiel #1
0
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()