Exemple #1
0
class Parser(object):

    A_CMD = 'A_COMMAND'
    C_CMD = 'C_COMMAND'
    L_CMD = 'L_COMMAND'

    def __init__(self, file_name):
        self.lines = []
        self.current_position = 0
        self.symbol_table = SymbolTable()
        self.readInFile(file_name)
        self.addLabelsToSymbolTable()
        self.substituteVars()

    def readInFile(self, file_name):
        with open (file_name, "r") as fp:
            for line in fp.readlines():
                line = line.strip()
                # skip empty newlines and comments
                if not line or line.startswith("//"):
                    continue
                self.lines.append(line.split()[0])

    def addLabelsToSymbolTable(self):
        line_count = 1
        while (self.hasMoreCommands()):
            self.advance()
            if self.commandType() == Parser.L_CMD:
                # TODO check this, this is wonky
                self.symbol_table.addEntry(self.symbol(), line_count-1)
            else:
                line_count += 1
        # reset current_position after reading
        self.current_position = 0

    def substituteVars(self):
        while (self.hasMoreCommands()):
            self.advance()
            if self.commandType() != Parser.A_CMD:
                continue
            var = self.symbol()
            if var.isdigit():
                continue
            if not self.symbol_table.contains(var):
                self.symbol_table.addEntry(var)
            self.lines[self.current_position-1] = "@{}".format(self.symbol_table.getAddress(var))
        # reset current_position after reading
        self.current_position = 0

    def commandType(self):
        if not self.current_command:
            raise Exception("current_command is empty")

        if self.current_command.startswith("@"):
            return self.A_CMD

        if self.current_command.startswith("("):
            return self.L_CMD

        return self.C_CMD

    def hasMoreCommands(self):
        return self.current_position < len(self.lines)

    def advance(self):
        self.current_command = self.lines[self.current_position]
        self.current_position += 1

    def symbol(self):
        return self.current_command.strip("@()")

    def dest(self):
        if len(self.current_command.split("=")) == 2:
            return self.current_command.split("=")[0]

    def comp(self):
        if len(self.current_command.split(";")) == 2:
            return self.current_command.split(";")[0]
        elif len(self.current_command.split("=")) == 2:
            return self.current_command.split("=")[1]

    def jump(self):
        if len(self.current_command.split(";")) == 2:
            return self.current_command.split(";")[1]
    register_symble(parser, symbol_table)
    parser.reset_idx()

    while parser.hasMoreCommands():

        parser.advance()
        cmdtype = parser.commandType()
        if cmdtype == "A_COMMAND":
            symbol = parser.symbol()
            if re.search("[A-Za-z]", symbol) != None:
                if symbol_table.contains(symbol):
                    address = symbol_table.getAddress(symbol)  #16進数
                else:
                    address = format(ram_address, '04x')  #16進数
                    symbol_table.addEntry(symbol, address)
                    ram_address += 1

                symbol = int(address, 16)

            binary = bin(int(symbol))[2:]
            bit16 = ("0" * (16 - len(binary))) + binary

        elif cmdtype == "C_COMMAND":
            dest_bin = code.dest2bin(parser.dest())
            comp_bin = code.comp2bin(parser.comp())
            jump_bin = code.jump2bin(parser.jump())
            bit16 = "111" + comp_bin + dest_bin + jump_bin

        else:
            continue  # L_COMMAND((Xxx))はバイナリコードへ変換した際に削除される形式なので飛ばす
Exemple #3
0
   def assemble(self):
      #
      # first pass - build the symbol table for labels
      #

      parser = Parser(self.source_filename)
      symbol_table = SymbolTable()

      # the current instruction
      instruction = 0

      # parse each command
      while parser.hasMoreCommands():
         # advance to the next command
         parser.advance()

         # parse the command type and look for symbols
         command_type = parser.commandType()
         if command_type == "L":
            # look for an instruction label symbol
            symbol = parser.symbol()
            if symbol not in symbol_table:
               symbol_table.addEntry(symbol, instruction)
         else:
            # increment the instruction count if this was not a label
            if command_type != "L":
               instruction += 1

      #
      # second pass - build the symbol table for variables
      #

      parser = Parser(self.source_filename)

      # the memory location for the next variable
      variable_address = 16

      # parse each command
      while parser.hasMoreCommands():
         # advance to the next command
         parser.advance()

         # parse the command type and look for symbols
         command_type = parser.commandType()
         if command_type == "A":
            # look for a variable value symbol
            symbol = parser.symbol()
            if symbol[0] not in map(str, range(0, 10)):
               # the symbol is not a number; that is, it is actually a symbol
               if symbol not in symbol_table:
                  symbol_table.addEntry(symbol, variable_address)
                  variable_address += 1

      #
      # third pass - generate assembly
      #

      parser = Parser(self.source_filename)
      code = Code()

      # parse all commands
      while parser.hasMoreCommands():
         # advance to the next command
         parser.advance()

         command_type = parser.commandType()
         if command_type == "A":
            # a command
            symbol = parser.symbol()
            if symbol in symbol_table:
               symbol = symbol_table.getAddress(symbol)

            symbol_binary = code.decimalToBinary(symbol)

            self.destination_file.write("0" + symbol_binary + "\n")
         elif command_type == "C":
            # c command
            comp = code.comp(parser.comp())
            dest = code.dest(parser.dest())
            jump = code.jump(parser.jump())

            self.destination_file.write("111" + comp + dest + jump + "\n")
         elif command_type == "L":
            # label - do nothing in this stage
            pass
         else:
            # unknown command
            raise Exception("ERROR: Unknown command type encountered")

      # close the output file
      self.destination_file.close()
#a_command_set = set()
a_command_list = []

while asm.hasMoreCommands():

    asm.advance()
    current_command = asm.currentCommand
    current_command_type = asm.commandType()

    if current_command_type == 'L_COMMAND':
        #get the symbol and
        symbol = asm.symbol()
        #add the symbol into the table only if it does not already exist
        if not symbol_table.contains(symbol):
            #add the symbol
            symbol_table.addEntry(symbol, l_command_address)

        continue

    if current_command_type == 'A_COMMAND':

        #get the symbol
        symbol = asm.symbol()
        #check to see if it really is a symbol or just a number
        if not symbol.isdigit():
            if symbol not in a_command_list:
                a_command_list.append(symbol)

        l_command_address += 1
        continue
Exemple #5
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 #6
0
class Parser:
    def __init__(self, assembly_path: str) -> None:
        self.coder = Code()
        self.symbol_table = SymbolTable()
        self.assembly = []
        self.idx = 0

        f = open(assembly_path, 'r')
        while True:
            line = f.readline()
            if not line: break
            if line[:2] == "//": continue
            if [e for e in line if e != " "] == ["\n"]:
                continue
            self.assembly.append(line)
        f.close()

    def reset_idx(self):
        self.idx = 0

    def hasMoreCommands(self) -> bool:
        return self.idx < len(self.assembly)

    def advance(self) -> None:
        if self.hasMoreCommands():
            self.idx += 1

    def commandType(self) -> str:
        if self.hasMoreCommands():
            curr = self.assembly[self.idx]

            if "@" in curr:
                print("A", curr)
                return A
            elif "=" in curr or ";" in curr:
                print("C", curr)
                return C
            elif "(" in curr:
                return L
            else:
                return None

    def symbol(self) -> str:
        symbol = "".join([s for s in self.assembly[self.idx] if s != " "])
        symbol = symbol.split("\n")[0]
        if self.commandType() == A:
            symbol = symbol[1:]
            if not self.symbol_table.contains(symbol):
                try:
                    address = int(symbol)
                    self.symbol_table.addEntry(symbol, str(address))
                except:
                    self.symbol_table.addEntry(symbol,
                                               str(self.symbol_table.idx))
                    self.symbol_table.advance()
            self.assembly[
                self.idx] = "@" + self.symbol_table.getAddress(symbol)
        elif self.commandType() == L:
            symbol = symbol[1:-1]
            if not self.symbol_table.contains(symbol):
                self.symbol_table.addEntry(symbol, str(self.idx))
            self.assembly = self.assembly[:self.idx] + self.assembly[self.idx +
                                                                     1:]
        else:
            return ""

        return self.symbol_table.getAddress(symbol)

    def dest(self) -> str:
        if self.commandType() == C:
            return self.coder.dest(self.assembly[self.idx])
        else:
            raise NotImplementedError

    def comp(self) -> str:
        if self.commandType() == C:
            return self.coder.comp(self.assembly[self.idx])
        else:
            raise NotImplementedError

    def jump(self) -> str:
        if self.commandType() == C:
            return self.coder.jump(self.assembly[self.idx])
        else:
            raise NotImplementedError

    # def address(self) -> str:
    #     if self.commandType() == A:
    #         return self.coder.address(self.assembly[self.idx])
    #     else:
    #         raise NotImplementedError

    def address(self) -> str:
        instruction = self.assembly[self.idx]
        instruction = "".join([i for i in instruction if i != " "])
        instruction = instruction[1:].split("\n")[0]
        if self.symbol_table.contains(instruction):
            address = self.symbol_table.getAddress(instruction)
        else:
            address = instruction

        b = bin(int(address))[2:]
        address = "0" * (16 - len(b)) + b
        return address
class AssemblerSymb:

    def __init__(self, path):
        self.parser = Parser(path)
        self.code = Code()
        self.symb_table = SymbolTable()
        ind1 = path.find('/')
        ind2 = path.find('.')
        writefile = path[:ind1] + "/" + path[ind1+1:ind2]
        self.file = open(writefile + '2.hack', 'w')

    def binary(self, s):
        return "{0:b}".format(int(s))

    def firstPass(self):
        counter = 0
        while self.parser.hasMoreCommands():
            self.parser.advance()
            command_type = self.parser.commandType()
            if command_type in ['A_COMMAND', 'C_COMMAND']:
                counter += 1
            elif command_type == 'L_COMMAND':
                symbol = self.parser.symbol()
                self.symb_table.addEntry(symbol, counter)
            else:
                raise ValueError("Unexpected command type encountered")

    def secondPass(self):
        ram_address = 16
        self.parser.i = -1
        while self.parser.hasMoreCommands():
            self.parser.advance()
            command_type = self.parser.commandType()
            if command_type == 'A_COMMAND':
                symbol = self.parser.symbol()
                if (not symbol.isdigit()) and (not self.symb_table.contains(symbol)):
                    self.symb_table.addEntry(symbol, ram_address)
                    ram_address += 1

    def createOutput(self):
        self.parser.i = -1
        while self.parser.hasMoreCommands():
            self.parser.advance()
            command_type = self.parser.commandType()
            # if A command
            if command_type == 'A_COMMAND':
                symbol = self.parser.symbol()
                if symbol.isdigit():
                    bin_symbol = self.binary(symbol)
                else:
                    symb_add = self.symb_table.getAddress(symbol)
                    bin_symbol = self.binary(symb_add)
                a_command = '0' * (16 - len(bin_symbol)) + bin_symbol
                self.file.write(a_command + '\n')
            elif command_type == 'C_COMMAND':
                dest_mnem = self.parser.dest()
                dest = self.code.dest(dest_mnem)
                comp_mnem = self.parser.comp()
                comp = self.code.comp(comp_mnem)
                jump_mnem = self.parser.jump()
                jump = self.code.jump(jump_mnem)
                c_command = '111' + comp + dest + jump
                self.file.write(c_command + '\n')
            else:
                pass
        self.file.close()