コード例 #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
ファイル: main.py プロジェクト: samreising/nand2tetris
    def main():
        filename = sys.argv[1]
        output = open(filename.split('.')[0] + '.hack', 'w')

        firstPass = Parser(filename)
        symbolTable = SymbolTable()
        rom_address = 0
        ramAddress = 16

        # First pass adds L_COMMANDs and ROM addresses to symbol table
        while firstPass.hasMoreCommands():
            firstPass.advance()
            command = firstPass.commandType()
            if command == 'A_COMMAND' or command == 'C_COMMAND':
                rom_address += 1
            elif command == 'L_COMMAND':
                symbolTable.addEntry(firstPass.symbol(), rom_address)

        # When A_COMMAND is encountered:
        #   if symbol is a digit write it to file
        #   if symbol is not a digit, look it up in the symbol table. If it's there, write the address
        #   if symbol is not a digit, look it up in the symbol table. If it is not there, add it then write the address
        secondPass = Parser(filename)
        while secondPass.hasMoreCommands():
            secondPass.advance()
            command = secondPass.commandType()
            symbol = secondPass.symbol()
            if command == 'A_COMMAND' and symbol:
                if symbol.isdigit():
                    output.write('0' + '{0:015b}'.format(int(symbol)) + '\n')
                elif symbolTable.contains(symbol):
                    symbolAddress = symbolTable.getAddress(symbol)
                    output.write('0' + '{0:015b}'.format(int(symbolAddress)) +
                                 '\n')
                else:
                    symbolTable.addEntry(symbol, ramAddress)
                    ramAddress += 1
                    symbolAddress = symbolTable.getAddress(symbol)
                    output.write('0' + '{0:015b}'.format(int(symbolAddress)) +
                                 '\n')
            else:
                dest = Code.dest(secondPass.dest())
                jump = Code.jump(secondPass.jump())
                comp = Code.comp(secondPass.comp())
                if comp != None:
                    output.write('111' + comp + dest + jump + '\n')

        output.close()
コード例 #3
0
ファイル: assembler.py プロジェクト: ccard/csci410python
#------------------------------------------------------------------------------
# Main
#------------------------------------------------------------------------------

#Builds the symbol table
while par.hasMoreCommands():
	par.advance()
	cType = par.commandType()
	#if the command type is a label
	if re.search('L_COMMAND',cType) is not None:
		temp_L = re.search('(.*)(;)(.*)',par.symbol())
		symT.addEntry(temp_L.group(1),int(temp_L.group(3)),False)

	#if it is an adddress type command
	elif re.search('A_COMMAND',cType) is not None:
		if not symT.contains(par.symbol()):
			#explicitly defind address
			if re.search('^[0-9]+',par.symbol()) is not None:
				symT.addEntry(par.symbol(),int(par.symbol()),False)
			else:
				symT.addEntry(par.symbol(),user_def_count,True)
	
#End loop


OUT=open(out_file,'w')
par2 = Parser(in_file,extended_op)

toWrite=''
output=''
コード例 #4
0
ファイル: assembler.py プロジェクト: kjlundsgaard/Nand2Tetris
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
コード例 #5
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')