Ejemplo n.º 1
0
def main(infile):
    # read the input file into a list, remove whitespace
    input = []
    binary_lines = []
    with open(infile) as f:
        input = f.readlines()

    # first pass, build symbol table
    parser = Parser(input)
    symbol_table = SymbolTable()
    rom_addr = 0
    while parser.has_more_commands():
        parser.advance()
        try:
            if parser.command_type(
            ) == parser.C_COMMAND or parser.command_type() == parser.A_COMMAND:
                rom_addr += 1
            elif parser.command_type() == parser.L_COMMAND:
                symbol = parser.symbol()
                symbol_table.add_entry(symbol, rom_addr)
        except ParseError as err:
            print("Parser error. Expression: {}. Error detail: {}".format(
                err.expression, err.message))
            exit(1)

    # second pass
    parser = Parser(input)
    ram_addr = 16
    while parser.has_more_commands():
        parser.advance()
        try:
            if parser.command_type() == parser.A_COMMAND:
                symbol = parser.symbol()

                try:
                    # if the symbol is a constant (int), translate it
                    int_symbol = int(symbol)
                    binary_lines.append(translate_a_instruction(int_symbol))
                except ValueError:
                    # symbol is not an integer, so either look it up, or its a new variable
                    if symbol_table.contains(symbol):
                        binary_lines.append(
                            translate_a_instruction(
                                symbol_table.get_address(symbol)))
                    else:
                        symbol_table.add_entry(symbol, ram_addr)
                        binary_lines.append(translate_a_instruction(ram_addr))
                        ram_addr += 1
            elif parser.command_type() == parser.C_COMMAND:
                # Translate C command
                binary_lines.append(
                    translate_c_instruction(parser.comp(), parser.dest(),
                                            parser.jump()))
        except ParseError as err:
            print("Parser error. Expression: {}. Error detail: {}".format(
                err.expression, err.message))
            exit(1)

    # translation is done. output to new .hack file
    outfile = infile.replace(".asm", "")
    outfile = "{}.hack".format(outfile)
    with open(outfile, "w") as f:
        for line in binary_lines:
            f.write(line)
            f.write("\n")
Ejemplo n.º 2
0
def main(input):
    infiles = []
    # determine if the inputs is a directory or vmfile
    if re.search("\.vm$", input):
        # input is a single .vm file
        infiles.append(input)
        output = input.strip(".vm")
        output = "{}.asm".format(output)
    else:
        # input is a directory
        # output file name should be <dirname>.asm located in that directory
        try:
            files = os.listdir(input)
            for f in files:
                if re.search("\.vm$", f):
                    infiles.append(os.path.join(input, f))
            # generate output filename
            input = re.sub("/$", "", input)
            output = os.path.join(os.path.abspath(input),
                                  "{}.asm".format(os.path.split(input)[1]))
        except Exception as e:
            print("Error attempting to read directory: {}".format(e))
            exit(1)

    # if empty, output error and exit
    if not infiles:
        print("No files found with .vm suffix in {} directory. Exiting".format(
            input))
        exit(1)

    # single code generator for all vm files, single ASM output
    code_gen = CodeGenerator()
    asm_output = code_gen.generate_init()
    #asm_output = []

    # loop through all .vm files
    for file in infiles:
        # open and load the file into a list
        vm_input = []
        with open(file) as f:
            vm_input = f.readlines()
        vmfile = file.strip(".vm")
        vmfile = os.path.split(vmfile)[-1]

        # each vm file gets its own parser
        parser = Parser(vm_input)
        while parser.has_more_commands():
            # set vmfile name, used to generate static variable symbols
            code_gen.vmfile = vmfile
            parser.advance()
            try:
                if parser.command_type() is config.C_EMPTY_LINE:
                    # skip whitespace/blank lines
                    continue
                elif parser.command_type() in config.PUSH_POP_COMMANDS:
                    asm_output.extend(
                        code_gen.generate_push_pop(parser.command_type(),
                                                   parser.arg1(),
                                                   parser.arg2()))
                elif parser.command_type() == config.C_ARITHMETIC:
                    asm_output.extend(
                        code_gen.generate_arithmetic(parser.arg1()))
                elif parser.command_type() == config.C_LABEL:
                    asm_output.extend(code_gen.generate_label(parser.arg1()))
                elif parser.command_type() == config.C_GOTO:
                    asm_output.extend(code_gen.generate_goto(parser.arg1()))
                elif parser.command_type() == config.C_IF:
                    asm_output.extend(code_gen.generate_if(parser.arg1()))
                elif parser.command_type() == config.C_FUNCTION:
                    asm_output.extend(
                        code_gen.generate_function(parser.arg1(),
                                                   parser.arg2()))
                elif parser.command_type() == config.C_CALL:
                    asm_output.extend(
                        code_gen.generate_call(parser.arg1(), parser.arg2()))
                elif parser.command_type() == config.C_RETURN:
                    asm_output.extend(code_gen.generate_return())

            except ParseError as err:
                print(
                    "Parser error. Expression: <{}>. Error detail: {}".format(
                        err.expression, err.message))
                exit(1)
            except CodeError as err:
                print(
                    "Code generator error. Expression: <{}>. Error detail: {}".
                    format(err.expression, err.message))
                exit(1)

    # write out asm file
    with open(output, "w") as f:
        for line in asm_output:
            f.write(line)
            f.write("\n")