Example #1
0
class VMTranslator:
    def __init__(self, src: str):
        self.asm_file, self.vm_files = self._parse_files(src)
        print("Translate to %s." % self.asm_file)
        self.code_writer = CodeWriter(self.asm_file)

    def translates(self):
        for vm_file in self.vm_files:
            self._translate(vm_file)

    def _parse_files(self, file_path: str) -> (str, list):
        if not os.path.exists(file_path):
            raise IOError("No such file or directory.")

        if os.path.isfile(file_path) and file_path.endswith(VM_EXT):
            asm_file = file_path.replace(VM_EXT, ASM_EXT)
            vm_files = [file_path]

        elif os.path.isdir(file_path):
            dir_path = file_path[:-1] if file_path[-1] == "/" else file_path
            asm_file = dir_path + "/" + os.path.basename(dir_path) + ASM_EXT
            vm_files = self._find_all_files_with_ext(dir_path, "vm")
        else:
            raise IOError("No such file or directory.")

        return asm_file, vm_files

    def _find_all_files_with_ext(self, dir_path: str, ext: str) -> list:
        ext_files = []
        suffix = os.extsep + ext.lower()
        for cur_dir, _, files in os.walk(dir_path):
            for file in files:
                if file.lower().endswith(suffix):
                    ext_files.append(os.path.join(cur_dir, file))
        return ext_files

    def _translate(self, vm_file: str):
        parser = Parser(vm_file)
        self.code_writer.set_filename(vm_file)
        self.code_writer.write("// ----------  %s ----------" %
                               self.code_writer.current_vm_file)

        while parser.next_line():
            self.code_writer.write("// " + parser.command_line())

            if parser.command_type() == "C_ARITHMETIC":
                self.code_writer.write_arithmetic(parser.argn(0))
            elif parser.command_type() == "C_PUSH":
                self.code_writer.write_push(parser.argn(1), parser.argn(2))
            elif parser.command_type() == "C_POP":
                self.code_writer.write_pop(parser.argn(1), parser.argn(2))
            elif parser.command_type() == "C_LABEL":
                self.code_writer.write_label(parser.argn(1))
            elif parser.command_type() == "C_GOTO":
                self.code_writer.write_goto(parser.argn(1))
            elif parser.command_type() == "C_IF_GOTO":
                self.code_writer.write_if_goto(parser.argn(1))
            elif parser.command_type() == "C_FUNCTION":
                self.code_writer.write_function(parser.argn(1),
                                                int(parser.argn(2)))
            elif parser.command_type() == "C_CALL":
                self.code_writer.write_call(parser.argn(1),
                                            int(parser.argn(2)))
            elif parser.command_type() == "C_RETURN":
                self.code_writer.write_return()

            self.code_writer.write("")  # empty line
        self.code_writer.write("// ------------------------------\n")
Example #2
0
from parser import Parser
from code_writer import CodeWriter

arg_parser = argparse.ArgumentParser(description='Translate vm code into assembly code')
arg_parser.add_argument('path_input', help='The path for vm file *.vm or the directory path which contains *.vm files')
args = arg_parser.parse_args()


path_input = Path(args.path_input)
assert path_input.exists(), "Path not exists."

if path_input.is_dir():	# Translate all vm files in directory
    vmfiles = [f for f in path_input.glob('*.vm')]
    assert vmfiles, "No vm file in this directory."
    out_asm_file = path_input / (path_input.name + '.asm')	# Out asm file name same as directory name
    returned_contents = {}
    for vmfile in vmfiles:
        psr = Parser(vmfile)
        parse_result = psr.parse()
        returned_contents = {**returned_contents, **parse_result}	# Merge returned results to dict returned_contents
else:	# Translate one vm file
    vmfile = path_input
    out_asm_file = path_input.with_suffix('.asm')
    psr = Parser(vmfile)
    returned_contents = psr.parse()

cw = CodeWriter(returned_contents, out_asm_file)
cw.write()
print('Successfully translate to assembly ' + out_asm_file.as_posix())