Пример #1
0
def main(debug, b_reg):
    """
    in: bool debug, bool b register
    out: void
    """
    ML = []
    st = SymbolTable()
    if len(sys.argv) < 2:
        no_file_arg()
    input_file = sys.argv[1]
    name = os.path.splitext(input_file)[0]
    parsed = Parser(input_file, debug, b_reg)
    rom_address = 0
    ram_address = 16
    """
    First pass
    """
    while parsed.has_more_cmds():
        if parsed.command_type() == "C_COMMAND" or parsed.command_type() == "A_COMMAND":
            rom_address += 1
        elif parsed.command_type() == "L_COMMAND":
            st.add_entry(parsed.symbol(), rom_address)
        parsed.advance()
    parsed.reset()

    """
    Second pass
    """
    i = 0
    while parsed.has_more_cmds():
        cc = parsed.b_cc() # account for b reg
        command_type = parsed.command_type()
        if command_type == "A_COMMAND":
            """
            Handle A commands.
            """
            if st.contains(cc[1:]):
                ML.append(parsed.a_int_to_binary(st.get_address(cc[1:])))
            elif parsed.cc_is_int():
                ML.append(parsed.a_int_to_binary(cc))
            elif not st.contains(cc[1:]):
                st.add_entry(cc[1:], ram_address)
                ML.append(parsed.a_int_to_binary(str(st.get_address(cc[1:]))))
                ram_address += 1
        else:
            ML.append(parsed.c_to_binary(cc, command_type, st))
        parsed.advance()
        i += 1
    create_file(ML, name)
Пример #2
0
class Main(object):
    def __init__(self, f):
        self.asm_file = f
        self.table = SymbolTable()
        self.data = self.read_file()
        self.parser = Parser(self.data)
        self.commands = self.parser.commands
        self.translator = Translator()
        self.filename = self.asm_file.split(".")[0]

    def read_file(self):
        with open(self.asm_file) as f:
            data = f.readlines()
        return data

    def write_file(self, output_lines):
        with open('%sassembled.hack' % self.filename, 'w') as output_file:
            for line in output_lines:
                output_file.write(line + '\n')

    def assemble(self):
        self.first_pass()
        output_lines = self.second_pass()
        self.write_file(output_lines)

    def first_pass(self):
        program_line = 0
        for line in self.commands:
            # if we have encountered a label pseudocommand
            # check if it is in the table, if not assign it to value of next program line
            # don't increment program counter because this shouldn't count as a program line
            if line[0] == '(':
                if not self.table.contains(line[1:-1]):
                    self.table.add_entry(line[1:-1], program_line)
                continue
            # if none of these conditions are hit, keep incrementing program line
            program_line += 1

    def second_pass(self):
        translated_commands = []
        next_available_RAM = 16
        for line in self.commands:
            if line[0] == '@':
                symbol = line[1:]
                try:
                    # translate directly if @ is referencing a specific value
                    translated_commands.append('{0:016b}'.format(int(symbol)))
                    continue
                except ValueError:
                    pass
                # check if symbol is already in the symbol table and convert value to binary
                if self.table.contains(symbol):
                    translated_commands.append('{0:016b}'.format(
                        self.table.get_address(symbol)))
                # add symbol to symbol table, increment available RAM count, and translate to binary
                else:
                    self.table.add_entry(symbol, next_available_RAM)
                    next_available_RAM += 1
                    translated_commands.append('{0:016b}'.format(
                        self.table.get_address(symbol)))
            elif line[0] == '(':
                continue
            else:
                translated_commands.append(
                    self.translator.handle_C_instruction(line))
        return translated_commands
Пример #3
0
class Assembler():
    '''
    Takes a single .asm file as input and outputs a .hack file with the same name.
    The assembling takes three passes.
        - Preprocess: Remove whitespace and comments
        - First Pass: Generate symbol table and remove symbolic labels
        - Second Pass: Translates the .asm file into a .hack file, line by line.
    '''
    def __init__(self, filename):
        self._input = self.preprocess(filename)
        self._name = filename.split('/')[-1]
        self._name = self._name.split('.')[0]
        self._table = SymbolTable()
        self.first_pass()
        self._parser = Parser(self._input)
        self._output = []
        self._code = Code()
        self.second_pass()
        self.write_output()

    def preprocess(self, filename):
        with open(filename, 'r') as temp:
            assembly = temp.readlines()
        temp = []
        for line in assembly:
            # remove comments and white space
            line = line.split('//')[0].strip().replace(' ', '')
            if line:
                # if nonempty, then it should contain valid asm
                temp += [line]
        return temp

    def first_pass(self):
        rom_addr = 0
        temp = []
        for line in self._input:
            if '(' in line:
                symbol = line[1:-1]
                self._table.add_entry(symbol, rom_addr)
            else:
                temp += [line]
                rom_addr += 1
        self._input = temp

    def second_pass(self):
        while self._parser.has_more_commands():
            self._parser.advance()
            if self._parser.command_type() == 'A':
                # A type command
                value = self._parser.symbol()
                if set(value) <= set('0123456789'):
                    # symbol is a number
                    value = int(value)
                elif self._table.contains(value):
                    # symbol is a label
                    value = self._table.get_address(value)
                else:
                    # symbol is a variable
                    self._table.add_entry(value)
                    value = self._table.get_address(value)
                self._output += ['0' + "{0:015b}".format(value) + '\n']
            elif self._parser.command_type() == 'C':
                # C type command
                self._output += [
                    '111' + self._code.comp(self._parser.comp()) +
                    self._code.dest(self._parser.dest()) +
                    self._code.jump(self._parser.jump()) + '\n'
                ]

    def write_output(self):
        with open('hack/' + self._name + '.hack', 'w') as temp:
            temp.writelines(self._output)
        print(self._name + '.asm', 'translated to',
              'hack/' + self._name + '.hack')