예제 #1
0
def main(path):
    """
    Creates parser object and code writer object, transfers the relevant commands to the relevant methods.
    :param path: file path
    :return: void
    """
    directory = []
    if os.path.isdir(path):
        code_writer = cw.CodeWriter(os.path.join(path, os.path.basename(path))+".asm")
        directory = glob.iglob(os.path.join(path, "*.vm"))
    else:
        file_name = path[:-3]
        code_writer = cw.CodeWriter(file_name + ".asm")
        directory.append(path)

    for file in directory:
        # removing the file extension and send it to the setFileName
        f = os.path.basename(file)[:-3]
        code_writer.setFileName(f)
        # creating a relevant parser object
        parser = ps.Parser(file)
        while parser.hasMoreCommands():
            cmd = parser.commandType()
            if cmd == gc.C_PUSH or cmd == gc.C_POP:
                code_writer.writePushPop(cmd, parser.arg1(), parser.arg2())
            if cmd == gc.C_ARITHMETIC:
                code_writer.writeArithmetic(parser.arg1())
            parser.advance()
    code_writer.close()
예제 #2
0
 def test_function_command(self):
     cw = CodeWriter.CodeWriter('Test.vm')
     result = cw.convert_function_command('Foo.test', 2)
     expected = [
         '// function Foo.test 2',
         '(Foo.test)',  # Push 2 local vars
         '// C_PUSH constant 0',  # local 0
         '@0',  # D = i
         'D=A',
         '@SP',  # *SP = D
         'A=M',
         'M=D',
         '@SP',  # SP++
         'M=M+1',
         '// C_PUSH constant 0',  # local 1
         '@0',  # D = i
         'D=A',
         '@SP',  # *SP = D
         'A=M',
         'M=D',
         '@SP',  # SP++
         'M=M+1',
     ]
     cw.close()
     self.assertEqual(result, expected)
예제 #3
0
 def translate_files(self, inputfiles, outputfile):
     code_writer = CodeWriter.CodeWriter(outputfile)
     # TODO: initialize code writer in chapter 8
     if inputfiles:  # list of inputfiles is not empty
         for file in inputfiles:
             self.translate(file, code_writer)
     code_writer.close()
 def translate_all(self, infiles, outfile):
     if infiles != []:
         code_writer = CodeWriter.CodeWriter(outfile)
         code_writer.write_init()
         for infile in infiles:
             self._translate(infile, code_writer)
         code_writer.close_file()
예제 #5
0
def main():
    filepath = sys.argv[1]

    if not os.path.isfile(filepath):
        print("File path {} does not exist. Exiting...".format(filepath))
        sys.exit()

    asm_filepath = os.path.splitext(filepath)[0] + ".asm"

    print('Loading file: ' + filepath)
    parser = Parser.Parser(filepath)
    code_writer = CodeWriter.CodeWriter(asm_filepath)

    print('Running through all commands in VM code')
    while parser.has_more_commands():
        parser.advance()

        if parser.command_type == Constants.C_ARITHMETIC:
            code_writer.write_arithmetic(parser.arg1)
        elif parser.command_type in [Constants.C_PUSH, Constants.C_POP]:
            code_writer.write_push_pop(parser.command_type, parser.arg1,
                                       parser.arg2)

    print('Closing file: ' + filepath)
    code_writer.close()
def handle_files(files_list, full_file_path):
    """
    Main func go over the lines of the files
    :param files_list: list of files in the dir
    :param full_file_path : path to save to
    """
    if full_file_path is None:
        return
    code_writer = CodeWriter.CodeWriter(full_file_path)
    code_writer.write_init()
    for file_name in files_list:
        parser = Parser.Parser(
            os.path.join(os.path.split(full_file_path)[0], file_name))
        code_writer.set_file_name(file_name.replace(VM, ""))
        while parser.has_more_commands():
            parser.advance()
            command = parser.command_type()
            if command == Parser.C_POP or command == Parser.C_PUSH:
                code_writer.write_push_pop(command, parser.arg1(),
                                           parser.arg2())
            elif command == Parser.C_GOTO:
                code_writer.write_goto(parser.arg1())
            elif command == Parser.C_IF:
                code_writer.write_if(parser.arg1())
            elif command == Parser.C_CALL:
                code_writer.write_call(parser.arg1(), parser.arg2())
            elif command == Parser.C_RETURN:
                code_writer.write_return()
            elif command == Parser.C_FUNCTION:
                code_writer.write_function(parser.arg1(), parser.arg2())
            elif command == Parser.C_LABEL:
                code_writer.write_label(parser.arg1())
            else:
                code_writer.write_arithmetic(parser.arg1())
    code_writer.close()
예제 #7
0
def parse_files(path):
    """
    this function will parse given files in path (even if single file) by using parse_single_file
    :param path:
    :return:
    """
    if VM_SUFFIX in path:
        files = [os.path.basename(path)]
    else:
        files = [vm for vm in glob.glob(osjoin(path, '*' + VM_SUFFIX))]
    if os.path.isdir(path):
        output_file_path = path + "/" + path.rsplit('/', 1)[1]
    else:
        output_file_path = path.rsplit('.', 1)[0]
    output_file_path = output_file_path + ".asm"
    is_init = False
    for file in files:
        with open(file, mode='r') as curr_file:
            for line in curr_file.readlines():
                if 'Sys.init' in line:
                    is_init = True
        curr_file.close()
    writer = CodeWriter(output_file_path, files[0], len(files))
    if is_init:
        writer.writeInit()
    for file in files:
        writer.setFileName(file)
        parse_single_file(file, writer)
    writer.close()
예제 #8
0
def createWriterFromDir(input):
    # removing last slash if exists
    input = removeSlash(input)

    fileName = os.path.basename(input)
    outputFileName = input + os.sep + fileName + ASM_EXTENTION

    return CodeWriter.CodeWriter(outputFileName)
예제 #9
0
    def translate(self, input_files, output_file):
        writer = CodeWriter.CodeWriter(output_file)
        writer.writeInit()

        for input_file in input_files:
            self._translate(input_file, writer)

        writer.close()
예제 #10
0
 def __init__(self):
     """constructor: holds an instance of CodeWriter ( which consist the main translaring methods),
     and the VMTextLines- the list containing the original VM lines before translation"""
     self.codeWriter = CodeWriter()
     self.__translated_text = [
     ]  #the asm lines after translation by the CodeWriter
     self.VMTextLines = []  #the original VM lines to be translated
     self.first = True
예제 #11
0
    def Translate(self, path):

        #open files in a folder
        if os.path.isdir(path):
            fileName = ntpath.basename(path)
            new_file_name = path + "/" + fileName + ".asm"
            self.codeWriter = C.CodeWriter(new_file_name)
            files_in_dir = os.listdir(path)
            for file_in_dir in files_in_dir:
                if file_in_dir.endswith("vm"):
                    self.translateFile(path + "/" + file_in_dir)
        #open one file
        elif path.endswith("vm"):
            new_file_name = path[:-2] + "asm"
            self.codeWriter = C.CodeWriter(new_file_name)
            self.translateFile(path)

        self.codeWriter.close()
예제 #12
0
def main(argv):
    userInput = sys.argv[1]

    if os.path.isdir(userInput):
        if userInput.endswith("/"):
            userInput = userInput[0:-1]
        dirname = os.path.basename(userInput)
        outputFile = userInput + "/" + dirname + ".asm"
        code = CodeWriter.CodeWriter(outputFile)
        for file in os.listdir(userInput):
            if ".vm" in file.lower():
                code.setFileName(file)
                translateFile(userInput + "/" + file, code)
    else:
        outputFile = userInput.split('.')[0] + ".asm"
        code = CodeWriter.CodeWriter(outputFile)
        code.setFileName(userInput)
        translateFile(userInput, code)
예제 #13
0
 def test_label(self):
     cw = CodeWriter.CodeWriter('Test.vm')
     result = cw.convert_label_command('TEST_LABEL')
     expected = [
         '// label TEST_LABEL',
         '(TEST_LABEL)',
     ]
     cw.close()
     self.assertEqual(result, expected)
예제 #14
0
 def translate_all(self):
     '''
     Translates all the .vm files in file_list to assembly language 
     and save the output to file_out.
     '''
     code_writer = CodeWriter.CodeWriter(self.file_out)
     for file_in in self.files_in:
         self.translate(file_in, code_writer)
     code_writer.close()
예제 #15
0
 def test_goto(self):
     cw = CodeWriter.CodeWriter('Test.vm')
     result = cw.convert_goto_command('TEST_LABEL')
     expected = [
         '// goto TEST_LABEL',
         '@TEST_LABEL',
         '0;JMP',
     ]
     cw.close()
     self.assertEqual(result, expected)
예제 #16
0
    def __init__(self):
        self.parser = argparse.ArgumentParser(
            description='Transrate VM file or directory to single asm file.')
        self.parser.add_argument('path', type=str, help='vm file or directory')
        args = self.parser.parse_args()
        path = args.path

        if os.path.isfile(path):
            if path.endswith('.vm'):
                self.code_writer = CodeWriter.CodeWriter(
                    "{}.asm".format(path[:-3]))
                self.files = [path]
            else:
                raise Exception("path: file name should end with \".vm\".")
        elif os.path.isdir(path):
            if path.endswith('/'):
                path = path[:-1]
            self.code_writer = CodeWriter.CodeWriter("{}.asm".format(path))
            self.files = glob.glob(f"{path}/*.vm")
        else:
            raise Exception("Unsupport File Type.")
예제 #17
0
def doAll(name):
    """
    runs the translator for a specific ".vm" file, or, if given a directory
    name, runs the translator for all ".vm" files in directory
    :param name: file/directory name
    """
    if ".vm" in name:
        outputName = name.strip(VMConsts.SOURCE_SUFFIX) + VMConsts.OUT_SUFFIX
        codeWriter = CodeWriter.CodeWriter(outputName)
        codeWriter.writeInit()
        parseFile(name, codeWriter)
    else:
        outputName = name.split("/")[-1]
        outputName = name + "//" + outputName + VMConsts.OUT_SUFFIX
        codeWriter = CodeWriter.CodeWriter(outputName)
        codeWriter.writeInit()
        for fileName in os.listdir(name):
            if ".vm" in fileName:
                codeWriter.setCurrentFile(fileName.strip(".vm"))
                parseFile(name + "//" + fileName, codeWriter)
        codeWriter.close()
예제 #18
0
 def convert_all_files(self, input_files, output_file):
     """
     For each input file, commands contained in it are
     converted to assembly and written into one output
     file.
     """
     if input_files != []:
         code_writer = CodeWriter.CodeWriter(output_file)
         code_writer.write_init()
         for input_file in input_files:
             self.convert(input_file, code_writer)
         code_writer.close()
예제 #19
0
def main():
    filename = sys.argv[1]
    outfile = os.path.splitext(filename)[0] + '.asm'
    with ps.Parser(filename) as p:
        c = cw.CodeWriter(outfile)
        while p.hasMoreCommands():
            p.advance()
            if p.commandType() == ps.C_PUSH:
                c.writePushPop(ps.C_PUSH, p.arg1(), p.arg2())
            elif p.commandType() == ps.C_POP:
                c.writePushPop(ps.C_POP, p.arg1(), p.arg2())
            elif p.commandType() == ps.C_ARITHMETIC:
                c.writeArithmetic(p.command)
예제 #20
0
def main():
    path = sys.argv[1]

    if os.path.isfile(path):
        file_list = [sys.argv[1]]
        output_file = os.path.splitext(path)[0] + '.asm'
    else:
        if path[-1] != '/':
            path = path + '/'
        file_list = glob.glob(path + '*.vm')
        output_file = path + path.split('/')[-2] + '.asm'
        ## Sys.vm を file_list の先頭に
        index_of_sys = file_list.index(path + 'Sys.vm')
        file_list[0], file_list[index_of_sys] = \
            file_list[index_of_sys], file_list[0]

    c = cw.CodeWriter(output_file)
    iter_counter = 0

    for file in file_list:
        c.setFileName(file)
        if iter_counter == 0:  ## 初回だけ writeInit() を呼ぶ
            c.writeInit()
            iter_counter += 1
        with ps.Parser(file) as p:
            while p.hasMoreCommands():
                p.advance()

                c.f.write('\n')

                if p.commandType() == ps.C_ARITHMETIC:
                    c.writeArithmetic(p.command)
                elif p.commandType() == ps.C_PUSH:
                    c.writePushPop(ps.C_PUSH, p.arg1(), p.arg2())
                elif p.commandType() == ps.C_POP:
                    c.writePushPop(ps.C_POP, p.arg1(), p.arg2())
                elif p.commandType() == ps.C_LABEL:
                    c.writeLabel(p.arg1())
                elif p.commandType() == ps.C_GOTO:
                    c.writeGoto(p.arg1())
                elif p.commandType() == ps.C_IF:
                    c.writeIf(p.arg1())
                elif p.commandType() == ps.C_CALL:
                    c.writeCall(p.arg1(), p.arg2())
                elif p.commandType() == ps.C_RETURN:
                    c.writeReturn()
                elif p.commandType() == ps.C_FUNCTION:
                    c.writeFunction(p.arg1(), p.arg2())

    c.close()
예제 #21
0
 def __init__(self):
     parser = Parser.Parser(infile)
     codewriter = CodeWriter.CodeWriter()
     codewriter.setFileName(infile)
     while parser.hasMoreCommands():
         parser.advance()
         cmd = parser.command_type()
         if cmd == parser.C_ARITHMETIC:
             codewriter.writeArithmetic(parser.arg1())
         elif cmd == parser.C_PUSH or cmd == parser.C_POP:
             codewriter.writePushPop(parser.command_type(), parser.arg1(), parser.arg2())
         else:
             print ("other")
     codewriter.close()
예제 #22
0
    def translate(self, path):
        if os.path.isdir(path):
            output_path = path + '/' + os.path.basename(path) + '.asm'
        else:
            output_path = path.replace('.vm', '.asm')

        self._codeWriter = CodeWriter.CodeWriter(output_path)

        if os.path.isdir(path):
            vmFiles = [file for file in os.listdir(path) if file.endswith('.vm')]
            for vmFile in vmFiles:
                self._translateVMfile(path + '/' + vmFile)
        else:
            self._translateVMfile(path)
예제 #23
0
 def test_push_constant(self):
     cw = CodeWriter.CodeWriter('Test.vm')
     result = cw.convert_push_command('push', 'constant', 10)
     expected = [
         '// push constant 10',
         '@10',  # D = i
         'D=A',
         '@SP',  # *SP = D
         'A=M',
         'M=D',
         '@SP',  # SP++
         'M=M+1'
     ]
     cw.close()
     self.assertEqual(result, expected)
예제 #24
0
 def test_push_pointer_0(self):
     cw = CodeWriter.CodeWriter('test1.test')
     result = cw.convert_push_command('push', 'pointer', 0)
     expected = [
         '// push pointer 0',
         '@THIS',  # D = THIS
         'D=M',
         '@SP',  # *SP = D
         'A=M',
         'M=D',
         '@SP',  # SP++
         'M=M+1'
     ]
     cw.close()
     self.assertEqual(result, expected)
예제 #25
0
 def test_pop_pointer_0(self):
     cw = CodeWriter.CodeWriter('test1.test')
     result = cw.convert_pop_command('pop', 'pointer', 0)
     expected = [
         '// pop pointer 0',
         '@SP',  # SP--
         'M=M-1',
         '@SP',  # D = *SP
         'A=M',
         'D=M',
         '@THIS',  # THIS = D
         'M=D'
     ]
     cw.close()
     self.assertEqual(result, expected)
예제 #26
0
 def test_pop_pointer_1(self):
     cw = CodeWriter.CodeWriter('Test.vm')
     result = cw.convert_pop_command('pop', 'pointer', 1)
     expected = [
         '// pop pointer 1',
         '@SP',  # SP--
         'M=M-1',
         '@SP',  # D = *SP
         'A=M',
         'D=M',
         '@THAT',  # THAT = D
         'M=D'
     ]
     cw.close()
     self.assertEqual(result, expected)
예제 #27
0
 def test_pop_static(self):
     cw = CodeWriter.CodeWriter('Test.vm')
     result = cw.convert_pop_command('pop', 'static', 5)
     expected = [
         '// pop static 5',
         '@SP',  # SP--
         'M=M-1',
         '@SP',  # D = *SP
         'A=M',
         'D=M',
         '@Test.5',  # var = D
         'M=D'
     ]
     cw.close()
     self.assertEqual(result, expected)
예제 #28
0
 def test_push_pointer_1(self):
     cw = CodeWriter.CodeWriter('Test.vm')
     result = cw.convert_push_command('push', 'pointer', 1)
     expected = [
         '// push pointer 1',
         '@THAT',  # D = THAT
         'D=M',
         '@SP',  # *SP = D
         'A=M',
         'M=D',
         '@SP',  # SP++
         'M=M+1'
     ]
     cw.close()
     self.assertEqual(result, expected)
예제 #29
0
 def test_push_static(self):
     cw = CodeWriter.CodeWriter('Test.vm')
     result = cw.convert_push_command('push', 'static', 5)
     expected = [
         '// push static 5',
         '@Test.5',  # D = var
         'D=M',
         '@SP',  # *SP = D
         'A=M',
         'M=D',
         '@SP',  # SP++
         'M=M+1'
     ]
     cw.close()
     self.assertEqual(result, expected)
예제 #30
0
 def test_if_goto(self):
     cw = CodeWriter.CodeWriter('Test.vm')
     result = cw.convert_if_goto_command('TEST_LABEL')
     expected = [
         '// if-goto TEST_LABEL',
         '@SP',  # SP--
         'M=M-1',
         '@SP',  # D = *SP
         'A=M',
         'D=M',
         '@TEST_LABEL',  # if cond jump
         'D;JNE',  # if-goto just looking for any non-zero value
         # in order to be true
     ]
     cw.close()
     self.assertEqual(result, expected)