コード例 #1
0
    def test_starting_out(self):
        translator = Translator((100, 100))

        v1 = Vector2D([1, 1])
        translation1 = translator.translate(v1)
        self.assertEqual(translation1, Vector2D([60, 40]))

        v2 = Vector2D([-20, 0])
        translation2 = translator.translate(v2)
        self.assertEqual(translation2, Vector2D([-150, 50]))
コード例 #2
0
class Parser:
    def __init__(self, fileName):
        self.prog = None
        self.iProgLine = 0
        self.symCommand = ""
        self.binCommand = ""
        self.nCommand = 0
        self.isComment = False
        self.symCommandType = -1
        self.tranlator = Translator()
        self.symTable = SymTable()
        self.newFile = fileName + ".hack"
        return None

    def addData(self, data):
        self.prog = data
        return None

    def advance(self):
        # strip leading/trailing whitespaces, remove "/n" characters
        currentLine = self.prog[self.iProgLine].strip()
        self.iProgLine += 1
        # do not parse empty lines and comments
        if ('//' in currentLine):
            i = currentLine.find('/')
            currentLine = currentLine[:i].strip()
        if ('/*' in currentLine and '*/' in currentLine):
            i = currentLine.find('/')
            j = currentLine[i+1:].find('/')
            currentLine = (currentLine[:i] + currentLine[j+1:]).strip()
        if ('/*' in currentLine):
            self.isComment = True
            return False
        if ('*/' in currentLine):
            self.isComment = False
            return False
        if (self.isComment):
            return False
        if (not currentLine):
            return False
        if (currentLine.startswith("(")):
            return False
        self.symCommand = currentLine
        # select correct type of instruction
        if (currentLine.startswith("@")):
            self.symCommandType = cType.A_COMMAND
        else:
            self.symCommandType = cType.C_COMMAND
        self.nCommand += 1
        return True

    def symbol(self):
        value = ""
        if (self.symCommandType == cType.A_COMMAND):
            value = self.symCommand.strip("@")
        if (not value.isdigit()):
            if (self.symTable.contains(value)):
                value = self.symTable.getAddress(value)
            else:
                value = self.symTable.addEntry(value)
        return '{0:016b}'.format(int(value))

    def instructions(self):
        if (self.symCommandType != cType.C_COMMAND):
            return ("", "", "")
        i = self.symCommand.find('=')
        j = self.symCommand.find(';')
        if (i == -1 and j == -1):
            dest = 'null'
            comp = self.symCommand
            jump = 'null'
            return (dest, comp, jump)
        if (i == -1):
            dest = 'null'
            comp = self.symCommand[:j]
            jump = self.symCommand[j+1:]
            return (dest, comp, jump)
        if (j == -1):
            dest = self.symCommand[:i]
            comp = self.symCommand[i+1:]
            jump = 'null'
            return (dest, comp, jump)
        dest = self.symCommand[:i]
        comp = self.symCommand[i+1:j]
        jump = self.symCommand[j+1:]
        return (dest, comp, jump)

    def commandToBinary(self):
        if (self.symCommandType == cType.C_COMMAND):
            (dest, comp, jump) = self.instructions()
            cCommandBinary = self.tranlator.translate(dest, comp, jump)
            return '111' + cCommandBinary
        else:
            return self.symbol()

    def parse(self):
        self.symTable.addData(self.prog)
        self.symTable.findLabels()
        hackFile = open(self.newFile, 'w')
        while (self.iProgLine < len(self.prog)):
            if (self.advance()):
                binCommand = self.commandToBinary()
                hackFile.write(binCommand)
                hackFile.write("\n")
        return