Exemple #1
0
def main():
    parser = argparse.ArgumentParser(description='Process some integers.')
    parser.add_argument('asm_file', type=str, help='asm file')

    args = parser.parse_args()
    asm_file = args.asm_file

    save_file = os.path.splitext(asm_file)[0] + ".hack"

    st = SymbolTable()

    with HackParser(asm_file) as hp:

        op_address = 0

        while hp.advance() != None:
            cmd_type = hp.command_type()
            if cmd_type == A_COMMAND or cmd_type == C_COMMAND:
                op_address += 1
            elif cmd_type == L_COMMAND:
                st.add_entry(hp.symbol(), op_address)

    with HackParser(asm_file) as hp:

        with open(save_file, 'w') as wf:

            while hp.advance() != None:

                cmd_type = hp.command_type()

                if cmd_type == A_COMMAND:
                    symbol = hp.symbol()
                    m = symbol_pattern.match(symbol)

                    if m.group(1):  # @value
                        bincode = "0" + int2bin(int(m.group(1)), 15)
                    elif m.group(2):  # @symbol
                        symbol = m.group(2)
                        if st.contains(symbol):
                            address = st.get_address(symbol)
                            bincode = "0" + int2bin(address, 15)
                        else:
                            st.add_variable(symbol)
                            address = st.get_address(symbol)
                            bincode = "0" + int2bin(address, 15)

                elif cmd_type == C_COMMAND:
                    bincode = '111' + code_writer.comp(
                        hp.comp()) + code_writer.dest(
                            hp.dest()) + code_writer.jump(hp.jump())

                if cmd_type != L_COMMAND:
                    wf.write(bincode + '\n')
Exemple #2
0
def main():
    parser = argparse.ArgumentParser(description='Process some integers.')
    parser.add_argument('asm_file', type=str, help='asm file')

    args = parser.parse_args()
    asm_file = args.asm_file

    save_file = os.path.splitext(asm_file)[0] + ".hack"

    st = SymbolTable()

    with HackParser(asm_file) as hp:

        op_address = 0

        while hp.advance() != None:
            cmd_type = hp.command_type()
            if cmd_type == A_COMMAND or cmd_type == C_COMMAND:
                op_address += 1
            elif cmd_type == L_COMMAND:
                st.add_entry(hp.symbol(), op_address)

    with HackParser(asm_file) as hp:

        with open(save_file, 'w') as wf:

            while hp.advance() != None:

                cmd_type = hp.command_type()

                if cmd_type == A_COMMAND:
                    symbol = hp.symbol()
                    m = symbol_pattern.match(symbol)

                    if m.group(1):  # @value
                        bincode = "0" + int2bin(int(m.group(1)), 15)
                    elif m.group(2):  # @symbol
                        symbol = m.group(2)
                        if st.contains(symbol):
                            address = st.get_address(symbol)
                            bincode = "0" + int2bin(address, 15)
                        else:
                            st.add_variable(symbol)
                            address = st.get_address(symbol)
                            bincode = "0" + int2bin(address, 15)

                elif cmd_type == C_COMMAND:
                    bincode = '111' + code_writer.comp(hp.comp()) + code_writer.dest(hp.dest()) + code_writer.jump(hp.jump())

                if cmd_type != L_COMMAND:
                    wf.write(bincode + '\n')
Exemple #3
0
def second_pass():
    """
    docstring
    """
    code_parser = Parser(sys.argv[1])
    memory_counter = 16
    with open(output_file, 'w') as file_object:
        while (code_parser.has_more_commands()):
            code_parser.advance()
            word = ''
            if code_parser.command_type() == 'C_COMMAND':
                word = '111' + code_trans.comp(
                    code_parser.comp()) + code_trans.dest(
                        code_parser.dest()) + code_trans.jump(
                            code_parser.jump()) + '\n'
            elif code_parser.command_type() == 'A_COMMAND':
                if is_integer(code_parser.symbol()):
                    word = binary_word(code_parser.symbol()) + '\n'
                elif SymbolTable.contains(code_parser.symbol()):
                    word = SymbolTable.get_address(code_parser.symbol()) + '\n'
                elif not SymbolTable.contains(code_parser.symbol()):
                    SymbolTable.add_entry(code_parser.symbol(),
                                          binary_word(memory_counter))
                    word = binary_word(memory_counter) + '\n'
                    memory_counter = memory_counter + 1
            elif code_parser.command_type() == 'L_COMMAND':
                pass
            file_object.write(word)
Exemple #4
0
def main():
    filename = sys.argv[1].split('.')[0]
    symbol_table = SymbolTable()
    first_iter(symbol_table)
    parser = Parser(filename)
    code = Code()
    output = []
    address = 16
    while (parser.has_more_commands()):
        parser.advance()

        if parser.command_type() == 'C_COMMAND':
            dest = parser.dest()
            comp = parser.comp()
            jump = parser.jump()
            # print(parser.current_command, code.dest(dest), code.comp(comp), code.jump(jump))
            output.append("111" + code.comp(comp) + code.dest(dest) +
                          code.jump(jump))
        else:
            symbol = parser.symbol()

            try:
                symbol_address = int(symbol)
            except:
                if not symbol_table.contains(symbol):
                    symbol_table.add_entry(symbol, address)
                    address += 1
                symbol_address = symbol_table.get_address(symbol)
            finally:
                output.append(bin(symbol_address)[2:].zfill(16))
                # print(parser.current_command, bin(symbol_table.get_address(symbol)))

            # if not symbol_table.contains(symbol):
            # 	symbol_table.add_entry(symbol, address)
            # 	address += 1
            # 	symbol_address = symbol_table.get_address(symbol)
            # 	print(symbol_address)
            # 	output.append(bin(symbol_table.get_address(symbol))[2:].zfill(16))
            # 	print(parser.current_command, bin(symbol_table.get_address(symbol)))

            # print(symbol_address)
            # output.append(bin(symbol_table.get_address(symbol))[2:].zfill(16))
            # print(parser.current_command, bin(symbol_table.get_address(symbol)))

    parser.close()
    hack_file = open(filename + '.hack', 'w')
    for line in output:
        hack_file.write(line + '\n')
    hack_file.close()
Exemple #5
0
    def two_pass_assembly(self):
        symbol_table = SymbolTable()
        rom_address = 0
        print("starting first pass")
        while(self.parser.has_more_commands()):
            cmd = self.parser.get_current_command()
            if(self.parser.commands.L_COMMAND==self.parser.command_type()):
                print "L: " + self.parser.symbol()
                symbol_table.add_entry(self.parser.symbol(),rom_address)
            else:
                rom_address += 1
            self.parser.advance()
            
        self.parser.reset()


        #the second pass is the same as the first without the print statements, 
        #and without handling (Xxx) syntax

        print("starting second pass")
        while(self.parser.has_more_commands()):
            cmd = self.parser.get_current_command()
            if(self.parser.commands.A_COMMAND==self.parser.command_type()):
                sym = self.parser.symbol()                
                if(sym.isdigit()):
                    val = sym
                else:
                    if(symbol_table.contains(sym)):
                        val = symbol_table.get_address(sym)
                    else:
                        symbol_table.add_entry(sym, rom_address)
                        rom_address += 1
                        val = rom_address
                
                self.parser.output.write("0" + '{0:015b}'.format(int(val))+"\n")

            elif(self.parser.commands.C_COMMAND==self.parser.command_type()):
                self.parser.output.write("111" 
                                         + self.code.comp(self.parser.comp()) 
                                         + self.code.dest(self.parser.dest()) 
                                         + self.code.jump(self.parser.jump())
                                         +"\n")
            self.parser.advance()
class Assembler:
    def __init__(self):
        self._code = Code()
        self._lexer = Lexer()
        self._parser = Parser()
        self._symbol_table = SymbolTable()

    def assemble(self, path):
        # Read file content
        content = self._read_file_contents(path)
        # Lex the file contents
        self._lexer.lex(content)
        # Pass the tokens to ther parser
        self._parser.set_tokens(self._lexer.tokens())
        # Build symbols
        self._build_symbols()
        # Translate to symbolless asm
        self._write_symbolless_asm(path)
        # Translate binary
        self._write_binary(path)

    def _write_symbolless_asm(self, path):
        basename = os.path.basename(path)
        name = basename.rsplit('.asm', 1)[0]
        file = open('%s/%sL.asm' % (os.path.dirname(path), name), 'w')
        self._parser.reset_pos()
        while self._parser.has_commands():
            command_type = self._parser.command_type()
            if command_type is Command.L_COMMAND:
                self._parser.advance()
                continue
            elif command_type is Command.A_COMMAND:
                value = None
                symbol = self._parser.symbol()
                if symbol is not None:
                    value = self._symbol_table.get_address(symbol)
                    if value is None:
                        sys.stderr.write('[Assembler]: Symbol not defined %s' %
                                         symbol)
                        file.close()
                        sys.exit(1)
                else:
                    value = self._parser.value()
                file.write('@%s' % value)
            elif command_type in [
                    Command.C_COMMAND_JMP, Command.C_COMMAND_COMP
            ]:
                file.write(self._parser.text())
            file.write('\n')
            self._parser.advance()
        file.close()

    def _write_binary(self, path):
        basename = os.path.basename(path)
        name = basename.rsplit('.asm', 1)[0]
        file = open('%s/%s.hack' % (os.path.dirname(path), name), 'w')
        binary = self._translate()
        file.write(binary)
        file.close()

    def _build_symbols(self):
        symbols_count = 0
        self._init_symbol_table()
        # First pass - get label symbols
        while self._parser.has_commands():
            if self._parser.command_type() is Command.L_COMMAND:
                symbol = self._parser.symbol()
                if self._symbol_table.contains(symbol):
                    sys.stderr.write(
                        '[Assembler]: Symbol %s is used more than once' %
                        symbol)
                    sys.exit(1)
                address = self._parser.pos() - symbols_count
                self._symbol_table.add_entry(symbol, address)
                symbols_count += 1
            self._parser.advance()
        # Second pass - get variable symbols
        variable_address = 16
        self._parser.reset_pos()
        while self._parser.has_commands():
            command_type = self._parser.command_type()
            if command_type is Command.A_COMMAND:
                symbol = self._parser.symbol()
                if symbol is not None and \
                        not self._symbol_table.contains(symbol):
                    address = variable_address
                    self._symbol_table.add_entry(symbol, address)
                    variable_address += 1
            self._parser.advance()

    def _translate(self):
        output = ''
        self._parser.reset_pos()
        while self._parser.has_commands():
            command_type = self._parser.command_type()
            if command_type is Command.A_COMMAND:
                symbol = self._parser.symbol()
                if symbol is not None:
                    if not self._symbol_table.contains(symbol):
                        sys.stderr.write('[Assembler]: Unknown symbol: %s' %
                                         symbol)
                        sys.exit(1)
                    address = self._symbol_table.get_address(symbol)
                    output += self._to_binary(address) + '\n'
                else:
                    value = self._parser.value()
                    output += self._to_binary(int(value)) + '\n'
            elif command_type is Command.C_COMMAND_COMP:
                comp = self._code.comp(self._parser.comp())
                dest = self._code.dest(self._parser.dest())
                output += '111' + comp + dest + '000\n'
            elif command_type is Command.C_COMMAND_JMP:
                comp = self._code.comp(self._parser.comp())
                jump = self._code.jump(self._parser.jump())
                output += '111' + comp + '000' + jump + '\n'
            self._parser.advance()
        return output

    def _init_symbol_table(self):
        self._symbol_table.clear()
        entries = {
            'SP': 0,
            'LCL': 1,
            'ARG': 2,
            'THIS': 3,
            'THAT': 4,
            'SCREEN': 16384,
            'KBD': 24576,
        }
        # R0 to R15
        for address in range(16):
            entries['R%d' % address] = address
        # Initialize symbol table with predefined symbols
        for key, value in entries.items():
            self._symbol_table.add_entry(key, value)

    def _read_file_contents(self, path):
        file = open(path, 'r')
        content = file.read()
        file.close()
        return content

    def _to_binary(self, value):
        return format(value, '016b')
Exemple #7
0
class Assembler:
    def __init__(self, filename):
        self.asm_filename = filename
        self.hack_filename = self.asm_filename[:-3] + 'hack'
        self.outfile = open(self.hack_filename, 'w')

        self.parser = Parser(self.asm_filename)
        self.code = Code()
        self.symbol_table = SymbolTable()
        self.next_available_address = 16

    def translate(self):
        """Translates all the commands in the .asm file, writing the resulting
        binary code to the .hack file.
        """
        self.first_pass()
        self.parser.reset()
        self.second_pass()
        self.outfile.close()

    def first_pass(self):
        """Goes through the input file, adding all the labels to the symbol
        table.
        """
        label = self.parser.first_label()
        while not self.parser.is_done():
            self.symbol_table.add_entry(label, self.parser.label_address())
            label = self.parser.next_label()

    def second_pass(self):
        """Goes through the input file fo a second time, translating the
        commands into binary, and adding symbols to the symbol table as
        required.
        """
        while not self.parser.is_done():
            self.process_command()
            self.parser.next_command()

    def process_command(self):
        """Translates the current command of the parser, writing the
        corresponding binary command to the output file (including a newline
        character).
        """
        if self.parser.command_type() == 'C_COMMAND':
            self.process_c_command()
        elif self.parser.command_type() == 'A_COMMAND':
            self.process_a_command()
        else:  #Command is a label
            return

    def process_c_command(self):
        """Translates the current C-command of the parser, writing the
        corresponding binary command to the output file (including a newline
        character).
        """
        dest_binary = self.code.dest(self.parser.dest)
        comp_binary = self.code.comp(self.parser.comp)
        jump_binary = self.code.jump(self.parser.jump)
        binary_command = '111' + comp_binary + dest_binary + jump_binary
        self.outfile.write(binary_command + '\n')

    def process_a_command(self):
        """Translates the current C-command of the parser, writing the
        corresponding binary command to the output file (including a newline
        character).
        """
        symbol = self.parser.symbol

        if symbol.isnumeric():
            address = int(symbol)
        elif self.symbol_table.contains(symbol):
            address = self.symbol_table.get_address(symbol)
        else:
            address = self.next_available_address
            self.symbol_table.add_entry(symbol, address)
            self.next_available_address += 1

        binary_command = self.binary_number(address)
        self.outfile.write(binary_command + '\n')

    def binary_number(self, symbol):
        """Takes a decimal number in the form of a string and converts
        it to a 16-bit binary number in the form of a string.
        """
        binary = bin(int(symbol))
        return binary[2:].zfill(16)
Exemple #8
0
class Parser():
    """Parser: Encapsulates access to the input code. Reads an assembly language command, parses it, and provides convenient access to the command's components (fields and symbols). In addition, removes all white space and comments."""
    def __init__(self, in_file):
        """Get the input file and gets ready to parse it. Instantiate a Code2bin for binary translation"""
        self.in_file = in_file
        self.code2bin = Code2Bin()
        self.symb_table = SymbolTable()

    def read_in_file(self):
        """Read the input file and process lines, put lines containing codes to a buffer"""
        self.code_contents = []
        ROM_address = 0
        with open(self.in_file, 'r', encoding='utf_8') as inf:
            for line in inf:
                command = self.process(line)
                # If returned command is an empty line after processed, skip it
                if not command:
                    continue
                self.code_contents.append(command)
                cmd_type = self.command_type(command)
                if cmd_type == 'L_COMMAND':  # cmd_type is 'L_COMMAND', add new entry to the symbol table
                    symbol = self.get_symbol(command)
                    self.symb_table.add_entry(symbol, ROM_address)
                else:
                    ROM_address += 1

    def process(self, line):
        """Removes all white space and comments"""
        return line.split('//')[0].strip()

    def command_type(self, command):
        """
        Returns the type of the current command: 
        A_COMMAND for @Xxx where Xxx is either a symbol or a decimal number
        C_COMMAND for dest=comp;jump (Either the dest or jump fields may be empty. If dest is empty, the "=" is omitted; If jump is empty, the ";" is omitted.)
        L_COMMAND (pseudo-command) for (Xxx) where Xxx is a symbol
        """
        if '@' in command:
            return 'A_COMMAND'
        elif '=' in command or ';' in command:
            return 'C_COMMAND'
        elif '(' in command and ')' in command:
            return 'L_COMMAND'

    def get_symbol(self, command):
        """Returns the symbol or decimal Xxx of the current command @Xxx or (Xxx). Should be called only when command_type() is A_COMMAND or L_COMMAND."""
        return command.replace('@', '').replace('(', '').replace(')', '')

    def get_dest_comp_jump(self, command):
        """Returns the dest, comp, jump mnemonic in the current C-command. Should be called only when command_type()is C_COMMAND"""
        if ';' not in command:
            dest, comp = command.split('=')
            jump = 'null'
        elif '=' not in command:
            dest = 'null'
            comp, jump = command.split(';')
        else:
            dest = command.split('=')[0]
            comp, jump = command.split('=')[1].split(';')
            # jump = command.split('=')[1].split(';')[1]
        return dest, comp, jump

    def translate(self):
        """Second pass, translate code_contents to binary contens"""
        self.out_binarys = []
        available_RAM_address = 16
        for command in self.code_contents:
            cmd_type = self.command_type(command)
            if cmd_type == 'A_COMMAND':
                symbol = self.get_symbol(command)
                if symbol.isdigit():
                    binary_line = '0{:015b}'.format(int(symbol))
                    self.out_binarys.append(binary_line)
                elif self.symb_table.contains(symbol):
                    binary_line = '0{:015b}'.format(
                        int(self.symb_table.get_address(symbol)))
                    self.out_binarys.append(binary_line)
                else:
                    self.symb_table.add_entry(symbol, available_RAM_address)
                    binary_line = '0{:015b}'.format(available_RAM_address)
                    self.out_binarys.append(binary_line)
                    available_RAM_address += 1
            elif cmd_type == 'C_COMMAND':
                dest, comp, jump = self.get_dest_comp_jump(command)
                dest_binary = self.code2bin.dest2bin(dest)
                comp_binary = self.code2bin.comp2bin(comp)
                jump_binary = self.code2bin.jump2bin(jump)
                binary_line = '111' + comp_binary + dest_binary + jump_binary
                self.out_binarys.append(binary_line)

    def write_out_binarys(self):
        out_file = self.in_file.replace('asm', 'hack')
        with open(out_file, 'w', encoding='utf_8') as outf:
            for binary in self.out_binarys:
                outf.write(binary + '\n')
        print(out_file, 'finished assembling.')

    def parse(self):
        self.read_in_file()
        self.translate()
        self.write_out_binarys()
Exemple #9
0
  def main():
    filename      = os.path.join(os.getcwd(), Util.getCommandLineArg(1))
    first_parser  = Parser(filename)
    second_parser = Parser(filename)
    symbol_table  = SymbolTable()

    hack_filename = filename.replace('asm', 'hack')
    hack_file     = open(hack_filename, 'w')

    ann_filename  = filename.replace('asm', 'ann')
    ann_file      = open(ann_filename, 'w')

    rom_address = 0
    ram_address = 16

    assembly    = ''

    while first_parser.has_more_commands():
      first_parser.advance()

      if first_parser.command_type() is 'A_COMMAND' or first_parser.command_type() is 'C_COMMAND':
        rom_address += 1
      elif first_parser.command_type() is 'L_COMMAND':
        symbol_table.add_entry(first_parser.symbol(), rom_address, 'LAB')

    while second_parser.has_more_commands():
      second_parser.advance()
      machine_command = ''

      if second_parser.command_type() is 'A_COMMAND':
        if second_parser.symbol()[0].isdigit():
          binary = second_parser.symbol()
        else:
          if symbol_table.contains(second_parser.symbol()):
            binary = symbol_table.get_address(second_parser.symbol())
          else:
            binary = ram_address
            symbol_table.add_entry(second_parser.symbol(), ram_address, 'VAR')
            ram_address += 1

        machine_command = '{0:016b}\n'.format(int(binary))

        hack_file.write(machine_command)
      elif second_parser.command_type() is 'C_COMMAND':
        dest = Code.dest(second_parser.dest())
        comp = Code.comp(second_parser.comp())
        jump = Code.jump(second_parser.jump())

        machine_command = '111{0}{1}{2}\n'.format(comp, dest, jump)

        hack_file.write(machine_command)

      assembly = second_parser.original_command().strip()
      mc = machine_command.strip()

      annotated_machine = '{} {} {} {}'.format(mc[0:4], mc[4:8], mc[8:12], mc[12:16])

      symbolless_command = ''

      if second_parser.command_type() is 'L_COMMAND':
        symbolless_command = symbol_table.get_address(second_parser.symbol())
      elif second_parser.command_type() is 'A_COMMAND' and not second_parser.symbol().isdigit():
        symbolless_command = '@{}'.format(symbol_table.get_address(second_parser.symbol()))
      else:
        symbolless_command = second_parser.command

      annotated_command = '{:<39} {} {:<11} {}\n'.format(assembly, '//' if second_parser.command_type() else '', symbolless_command, annotated_machine)

      ann_file.write(annotated_command)

    ann_file.write('\n// Symbol Table:\n')

    for symbol, address in symbol_table.symbol_table.items():
      ann_file.write('// {}: {:<30} -> {}\n'.format(address[1], symbol, address[0]))

    hack_file.close()
    ann_file.close()
def main():

    # If there is an invalid number of arguments the program stops.
    if len(sys.argv) != 2:
        print("ERROR: Invalid number of arguments. Expected: file_name.asm ")
        exit(1)
    # The assembler only accepts asm files to be translated into hack files
    elif sys.argv[1][-4:] != ".asm":
        print("ERROR: Invalid file type. Expected: asm file")
        exit(1)

    input_file = sys.argv[1]

    # Initialize the symbol table with the predefined symbols.
    symbol_table = SymbolTable()
    translator_c_command = Code()

    # Counters to keep track of the ROM and RAM memory address.
    count_ROM = 0
    count_variable = 16

    # List containing all the translated commands from the file.
    commands_translation = []

    # First pass
    parser = Parser(input_file)
    # Reads the whole file.
    while parser.has_more_commands():
        parser.advance()
        # Checks if the current command is has a label to and adds it to the table.
        if parser.command_type() == "L_COMMAND":
            # Takes the symbol from the label.
            label = parser.symbol()
            # Check if the label does not start with a number and adds the symbol to the table.
            if not label[0].isdigit():
                symbol_table.add_entry(label, count_ROM)
            else:
                print("ERROR: invalid label indentifier")
                exit(1)
        else:
            # If it finds an A_COMMAND or C_COMMAND adds one to the ROM counter.
            count_ROM += 1

    # Reset the parser pointer to read the file
    parser.file.seek(0)

    # Second pass

    #Reads the whole file
    while parser.has_more_commands():
        parser.advance()
        # Checks if the current command is type "A_COMMAND".
        if parser.command_type() == "A_COMMAND":
            # Get the variable
            variable = parser.symbol()
            # Checks the variable starts with a letter.
            if not variable[0].isdigit():
                # If the table does not contain the symbol, adds it to the table, does the translation to binary code,
                # adds it to the list of translations and ads one to the RAM counter.
                if not symbol_table.contains(variable):
                    symbol_table.add_entry(variable, count_variable)
                    binary_address = "{:016b}".format(count_variable)
                    commands_translation.append(binary_address)
                    count_variable += 1
                # If the table contains the symbol, gets the address associated with the symbol,
                # does the translation to binary code and adds it to the translated list.
                else:
                    address = symbol_table.get_address(variable)
                    binary_address = "{:016b}".format(address)
                    commands_translation.append(binary_address)
            # Check if the variable is a number, translates it to its binary code and adds it to the translated list.
            elif variable.isdigit():
                binary_address = "{:016b}".format(int(variable))
                commands_translation.append(binary_address)
            # If the variable is not a number o starts with a letter theres a mistake in the command and the program stops.
            else:
                print("ERROR: The symbol " + variable + " is invalid")
                exit(1)
        # Check if the current command is type "C_COMMAND".
        elif parser.command_type() == "C_COMMAND":
            # Gets the dest, comp and jump mnemonic.
            command_dest = parser.dest()
            command_comp = parser.comp()
            command_jump = parser.jump()

            # Translates each mnemonic into its binary code.
            binary_dest = translator_c_command.dest(command_dest)
            binary_comp = translator_c_command.comp(command_comp)
            binary_jump = translator_c_command.jump(command_jump)
            # Put together all the binary codes addring three '1's at the beging and adds it to the translated list.
            binary_code = "111" + binary_comp + binary_dest + binary_jump
            commands_translation.append(binary_code)

    # Creates the hack file using the input file
    dot_index = input_file.find(".")
    hack_file = input_file[:dot_index] + ".hack"
    # Opens the hack file, if it does not exist creates it
    file = open(hack_file, "w")
    # For each command in the translated list, writes the binary code on the hack file and adds a new line
    for command in commands_translation:
        file.write(command)
        file.write("\n")
    # Close the hack file
    file.close()
    exit(0)
Exemple #11
0
            line_address += 1

    parser.seek_head()
    var_address = 16
    while parser.has_more_commands():
        parser.advance()

        if parser.command_type() == 'L_COMMAND':
            continue

        elif parser.command_type() == 'A_COMMAND':
            symbol = parser.symbol()
            if symbol.isdigit():
                address = int(symbol)
            elif symbol_table.contains(symbol):
                address = symbol_table.get_address(symbol)
            else:
                address = var_address
                symbol_table.add_entry(symbol, address)
                var_address += 1
            machine_code = address

        elif parser.command_type() == 'C_COMMAND':
            comp = Code.comp(parser.comp())
            dest = Code.dest(parser.dest())
            jump = Code.jump(parser.jump())
            machine_code = 0b111 << 13 | comp << 6 | dest << 3 | jump

        machine_code_str = "{0:016b}".format(machine_code)
        hack_file.write(machine_code_str + '\n')
Exemple #12
0
# If the address is already taken increment it by 1 until a free spot in RAM is found
# Generates all A and C-command mnemonics and binaries
while not assembly_program.is_parsed():
    current_command = assembly_program.advance()
    command_type = assembly_program.get_command_type(current_command)

    if command_type == 'A_COMMAND':
        symbol = current_command[1:]

        # Check if the A_COMMAND is a decimal number or a @symbol (variable)
        if assembly_program.is_decimal(symbol):
            translated_program.append(convert_to_bin(symbol))
        elif not symbol_table.contains_symbol(symbol):
            symbol_table.add_symbol(symbol)
            translated_program.append(
                convert_to_bin(symbol_table.get_address(symbol)))
        else:
            translated_program.append(
                convert_to_bin(symbol_table.get_address(symbol)))

    else:  # It's a C_COMMAND
        dest_mnemonics = assembly_program.get_dest_mnemonics(current_command)
        comp_mnemonics = assembly_program.get_comp_mnemonics(current_command)
        jump_mnemonics = assembly_program.get_jump_mnemonics(current_command)

        # Generate a Translator object,
        # which contains the converted command mnemonics to bits
        mnemonics_to_bin = Translator(dest_mnemonics, comp_mnemonics,
                                      jump_mnemonics)

        c_command_bin = '111' + mnemonics_to_bin.comp_bits + \
Exemple #13
0
class Assembler:
    def __init__(self):
        self.table = SymbolTable()
        self.address = 16

    def first_pass(self, filename):
        # first pass: advancing through file step by step to build up symbol table
        p = Parser(filename)
        current_address = 0
        while p.has_more_commands():
            p.advance()
            c_type = p.command_type()
            if c_type == Commands.C_COMMAND or c_type == Commands.A_COMMAND:
                # incrementing the instruction address
                current_address += 1
            elif c_type == Commands.L_COMMAND:
                # adding new symbol/label to table
                self.table.add_entry(p.symbol(), current_address)

    def second_pass(self, filename):
        # second pass: actually generate the binary for each instruction using the
        # symbol table built up from the first pass
        p = Parser(filename)

        # creating new file name, with .hack ending
        newfile = filename.split('.')[0] + '.hack'
        with open(newfile, 'w') as f:
            while p.has_more_commands():
                p.advance()
                c_type = p.command_type()
                if c_type == Commands.C_COMMAND:
                    d, c, j = p.tokenize_C_inst()
                    line = code.get_C_inst(d, c, j)
                elif c_type == Commands.A_COMMAND:
                    # we need to check if the symbol is in the table and get its value
                    line = code.get_A_inst(self.check_symbol(p.symbol()))
                else:
                    # if its anything else, don't write anything and start again from
                    # next line
                    continue

                # writing the line to file
                f.write(line + '\n')
        f.close()

    def check_symbol(self, symbol):
        # method for checking if the symbol is a symbol and getting its value
        # from the table
        if symbol.isdigit():
            # if it's a digit, then return itself since we want that value
            return symbol
        else:
            if symbol not in self.table.table:
                # if not in table, then add it to the table starting from address 16
                self.table.add_entry(symbol, self.address)
                self.address += 1
            return self.table.get_address(symbol)

    def assemble(self, filename):
        #print('First pass...')
        self.first_pass(filename)
        #print('Second pass...')
        self.second_pass(filename)
Exemple #14
0
class AssmParser(AssmCommandType, Parser):
    def __init__(self, file_name):
        """ Open the input file/stream and gets ready to parse it """
        super(AssmParser, self).__init__(file_name)
        self.RAM = 16

        self.symbol_table = SymbolTable(self.buff)
        self.symbol_table.find_symbols()

    def symbol(self):
        """
        returns the symbol or decimal Xxx of the current command @Xxx of (Xxx).
        Should be called only when commandType() is A_COMMAND or L_COMMAND

        return string
        """
        self.current_symbol = self.current_command[1:]

    def dest(self):
        """
        returns the dest mnemonic in the current C_COMMAND (8 possibilities).

        Should be called only when AssmCommandType() is C_COMMAND

        returns string
        """
        # semicolon: 000 dest
        if '=' in self.current_command:
            d = self.current_command.split('=')[0]
        else:
            d='null'

        code = Code()
        self.current_dest = code.dest(d)

    def comp(self):
        """
        Returns the comp menomonic in the current C_COMMAND (28 possibilities)
        Should be called only when commandType() is C_COMMAND

        return string
        """
        if '=' in self.current_command:
            c = self.current_command.split('=')[1]
        elif ';' in self.current_command:
            c = self.current_command.split(';')[0]

        code = Code()
        self.current_comp, self.current_a = code.comp(c)

    #def a(self):
        ##TODO: figure out how to know 'a' bit
        ## I believe it has to do whether the previous command is an l or a command
        #self.current_a = '0'

    def jump(self):
        """
        Returns the jump mnemonic in the current C_COMMAND (8 possibilities)
        Should be called only when commandType() is C_COMMAND

        returns string
        """
        # equal: 000 jump 
        if ';' in self.current_command:
            j = self.current_command.split(';')[1]
        elif '=' in self.current_command:
            j='null'
        else:
            j = None
        code = Code()
        self.current_jump = code.jump(j)

    def __repr__(self):
        return self.asmfile + '\n'.join(self.buff)

    def binarize_c_command(self):
        self.comp() 
        self.dest()
        self.jump()
        self.bin_current = '111' + self.current_a + self.current_comp + self.current_dest + self.current_jump


    def binarize_a_symbol(self):
        if not self.symbol_table.contains(self.current_command):
            self.symbol_table.addEntry(self.current_command, self.RAM)
            self.RAM = self.RAM + 1

        address = self.symbol_table.get_address(self.current_command)
        bin_address = bin(address)[2:]
        self.bin_current = '0' * (16 - len(bin_address))  + bin_address

    def binarize_a_address(self):
        address = int(self.current_command[1:])
        bin_address = bin(address)[2:]
        self.bin_current = '0'*(16 - len(bin_address))  + bin_address

    def binarize_a_command(self):
        if re.match(r'^@[0-9].*$', self.current_command):
            self.binarize_a_address()
        else:
            self.binarize_a_symbol()
Exemple #15
0
class Assembler(object):
    """
    lalala
    """
    def __init__(self, asm_file):
        self.asm_file = asm_file
        self.hack_file = ''.join([asm_file.split('.')[0], '.hack'])
        self.parser = Parser(asm_file)
        self.code = Code()
        self.symbol_table = SymbolTable()

    def assembly(self):
        print('Starting to assembly {} file...'.format(self.asm_file))
        with open(self.hack_file, 'w') as hack_f:

            ##################
            ### First pass ###
            ##################

            line_number = 0
            while self.parser.advance():
                command_type = self.parser.command_type()
                if command_type == self.parser.c_command or command_type == self.parser.a_command:
                    line_number += 1

                elif command_type == self.parser.l_command:
                    symbol = self.parser.symbol()
                    self.symbol_table.add_entry(symbol, line_number)

                else:
                    raise ValueError('Ups!')

            ###################
            ### Second pass ###
            ###################

            next_var_address = 16
            while self.parser.advance():
                command_type = self.parser.command_type()
                if command_type == self.parser.c_command:
                    dest_bin = self.code.dest_mnemonic[self.parser.dest()]
                    comp_bin = self.code.comp_mnemonic[self.parser.comp()]
                    jump_bin = self.code.jump_mnemonic[self.parser.jump()]
                    word_16 = ''.join(
                        ['111', comp_bin, dest_bin, jump_bin, '\n'])

                elif command_type == self.parser.a_command:
                    symbol = self.parser.symbol()
                    if symbol.isdigit():
                        address_bin = format(int(symbol), 'b').zfill(15)
                    else:
                        if self.symbol_table.contains(symbol) == False:
                            self.symbol_table.add_entry(
                                symbol, next_var_address)
                            next_var_address += 1

                        address_int = self.symbol_table.get_address(symbol)
                        address_bin = format(address_int, 'b').zfill(15)
                    word_16 = ''.join(['0', address_bin, '\n'])

                elif command_type == self.parser.l_command:
                    continue
                else:
                    raise ValueError('Ups!')
                hack_f.write(word_16)
        print('Successfully finished the assembly process :)')
Exemple #16
0
class Assembler:
    
    def __init__(self):
        self.table = SymbolTable()
        self.address = 16

    def first_pass(self, filename):
        # first pass: advancing through file step by step to build up symbol table
        p = Parser(filename)
        current_address = 0
        while p.has_more_commands():
            p.advance()
            c_type = p.command_type()
            if c_type == Commands.C_COMMAND or c_type == Commands.A_COMMAND:
                # incrementing the instruction address
                current_address += 1
            elif c_type == Commands.L_COMMAND:
                # adding new symbol/label to table
                self.table.add_entry(p.symbol(), current_address)

    def second_pass(self, filename):
        # second pass: actually generate the binary for each instruction using the
        # symbol table built up from the first pass
        p = Parser(filename)

        # creating new file name, with .hack ending
        newfile = filename.split('.')[0] + '.hack'
        with open(newfile, 'w') as f:
            while p.has_more_commands():
                p.advance()
                c_type = p.command_type()
                if c_type == Commands.C_COMMAND:
                    d, c, j = p.tokenize_C_inst() 
                    line = code.get_C_inst(d, c, j)
                elif c_type == Commands.A_COMMAND:
                    # we need to check if the symbol is in the table and get its value
                    line = code.get_A_inst(self.check_symbol(p.symbol()))
                else:
                    # if its anything else, don't write anything and start again from
                    # next line
                    continue

                # writing the line to file
                f.write(line + '\n')
        f.close()
    
    def check_symbol(self, symbol):
        # method for checking if the symbol is a symbol and getting its value
        # from the table
        if symbol.isdigit():
            # if it's a digit, then return itself since we want that value
            return symbol
        else:
            if symbol not in self.table.table:
                # if not in table, then add it to the table starting from address 16
                self.table.add_entry(symbol, self.address)
                self.address += 1
            return self.table.get_address(symbol)
   
    def assemble(self, filename):
        #print('First pass...')
        self.first_pass(filename)
        #print('Second pass...')
        self.second_pass(filename) 
Exemple #17
0
    def main():
        filename = os.path.join(os.getcwd(), Util.getCommandLineArg(1))
        first_parser = Parser(filename)
        second_parser = Parser(filename)
        symbol_table = SymbolTable()

        hack_filename = filename.replace('asm', 'hack')
        hack_file = open(hack_filename, 'w')

        ann_filename = filename.replace('asm', 'ann')
        ann_file = open(ann_filename, 'w')

        rom_address = 0
        ram_address = 16

        assembly = ''

        while first_parser.has_more_commands():
            first_parser.advance()

            if first_parser.command_type(
            ) is 'A_COMMAND' or first_parser.command_type() is 'C_COMMAND':
                rom_address += 1
            elif first_parser.command_type() is 'L_COMMAND':
                symbol_table.add_entry(first_parser.symbol(), rom_address,
                                       'LAB')

        while second_parser.has_more_commands():
            second_parser.advance()
            machine_command = ''

            if second_parser.command_type() is 'A_COMMAND':
                if second_parser.symbol()[0].isdigit():
                    binary = second_parser.symbol()
                else:
                    if symbol_table.contains(second_parser.symbol()):
                        binary = symbol_table.get_address(
                            second_parser.symbol())
                    else:
                        binary = ram_address
                        symbol_table.add_entry(second_parser.symbol(),
                                               ram_address, 'VAR')
                        ram_address += 1

                machine_command = '{0:016b}\n'.format(int(binary))

                hack_file.write(machine_command)
            elif second_parser.command_type() is 'C_COMMAND':
                dest = Code.dest(second_parser.dest())
                comp = Code.comp(second_parser.comp())
                jump = Code.jump(second_parser.jump())

                machine_command = '111{0}{1}{2}\n'.format(comp, dest, jump)

                hack_file.write(machine_command)

            assembly = second_parser.original_command().strip()
            mc = machine_command.strip()

            annotated_machine = '{} {} {} {}'.format(mc[0:4], mc[4:8],
                                                     mc[8:12], mc[12:16])

            symbolless_command = ''

            if second_parser.command_type() is 'L_COMMAND':
                symbolless_command = symbol_table.get_address(
                    second_parser.symbol())
            elif second_parser.command_type(
            ) is 'A_COMMAND' and not second_parser.symbol().isdigit():
                symbolless_command = '@{}'.format(
                    symbol_table.get_address(second_parser.symbol()))
            else:
                symbolless_command = second_parser.command

            annotated_command = '{:<39} {} {:<11} {}\n'.format(
                assembly, '//' if second_parser.command_type() else '',
                symbolless_command, annotated_machine)

            ann_file.write(annotated_command)

        ann_file.write('\n// Symbol Table:\n')

        for symbol, address in symbol_table.symbol_table.items():
            ann_file.write('// {}: {:<30} -> {}\n'.format(
                address[1], symbol, address[0]))

        hack_file.close()
        ann_file.close()