def assemble(self): # populate the symbol table w/ loop markers self.parse(self._firstPass) # aseemble the code self.parse(self._secPass) # write assembled code to .hack file fh.writeHackFile(self._filePath, self._codeList)
def _firstParse(self): for line in self._f: # remove the newline char '\n' line = line.strip() # check if there is parseable code in line if not fh.isCommentOrEmpty(line): line = fh.removeInlineComments(line) # update the clean code string self._code += line
def _secPass(self, line): line = fh.removeInlineComments(line) # check if it's a instruction if fh.isAInst(line): # handle a-instruction self._handleAInst(line[1:]) # else must be a c-instruction elif not fh.isLoopMarker(line): # handle c-instruction self._handleCInst(line)
def _handleAInst(self, aInst): address = '' # if a-inst is an int try: address = fh.dec2bin(int(aInst), 15) # else must be a symbol except: # decode the asm code decaddr = self._ht.symbolHandler(str(aInst)) address = fh.dec2bin(decaddr, 15) # store it in the code list self._codeList.append('0' + address + '\n')
def parse(self, asmLogicFunc): for line in self._f: # remove the newline char '\n' line = line.strip() # remove whitespaces from lines line = fh.removeSpaces(line) # check if there is parseable code in line if not fh.isCommentOrEmpty(line): # apply assembly logic to it asmLogicFunc(line) # reset the file cursor to the start of file self._f.seek(0)
def parse(self): for line in self._f: # remove the newline char '\n' line = line.strip() # check if there is parseable code in line if not fh.isCommentOrEmpty(line): line = fh.removeInlineComments(line) # split commands from the line commands = line.split(" ") # get the type of command cmdtype = cf.commandType(commands[0]) # if it's a push or pop command handle it if cmdtype == PUSH or cmdtype == POP: self._handlePushPop(commands, cmdtype) # else if it's a arithmetic command handle it elif cmdtype == ARITHMETIC: self._handleArithmetic(commands)
def _firstPass(self, line): # if line contain a loop marker if fh.isLoopMarker(line): loopMark = line[1:-1] # store it in the symbol hash table self._ht.addSymbol(loopMark, self._lineCount + 1) else: # count number of parseable code lines self._lineCount += 1
def parse(self): for line in self._f: # remove the newline char '\n' line = line.strip() # check if there is parseable code in line if not fh.isCommentOrEmpty(line): writeStr = "" # remove in-line comments from each line line = fh.removeInlineComments(line) # split commands from the line commands = line.split(" ") # get the type of command cmdtype = self._cf.commandType(commands[0]) # if it's a push or pop command handle it if cmdtype == PUSH or cmdtype == POP: writeStr = self._handlePushPop(commands, cmdtype) # else if it's a arithmetic command handle it elif cmdtype == ARITHMETIC: writeStr = self._handleArithmetic(commands) # else if it's a label command handle it elif cmdtype == LABEL: writeStr = self._cf.writeLabelAsm(commands[1]) # else if it's a goto command handle it elif cmdtype == GOTO: writeStr = self._cf.writeGotoAsm(commands[1]) # else if it's a if-goto command handle it elif cmdtype == IF: writeStr = self._cf.writeIfGotoAsm(commands[1]) # else if it's a call command handle it elif cmdtype == CALL: writeStr = self._cf.writeCallAsm(commands[1], int(commands[2])) # else if it's a return command handle it elif cmdtype == RETURN: writeStr = self._cf.writeReturnAsm() # else if it's a function command handle it elif cmdtype == FUNCTION: writeStr = self._cf.writeFunctionAsm(commands[1], int(commands[2])) # add it to the code list self._codeList.append(writeStr) print(line) print(self._codeList)
def _handlePushPop(self, commands, ptype): outStr = "" segment = commands[1]; index = int(commands[2]) segtype = self._cf.pushPopType(segment) # if it's a group 1 command write asm code for it if segtype == GROUP_1: outStr = self._cf.writePushPopAsm1(ptype, segment, index) elif segtype == STATIC: outStr = self._cf.writeStaticPushPopAsm(fh.getVmFileName(self._filePath), ptype, index) # if it's a group 2 command write asm code for it elif segtype == GROUP_2: outStr = self._cf.writePushPopAsm2(ptype, segment, index) # if it's a constant command write asm code for it elif segtype == CONSTANT: outStr = self._cf.writeConstantPushPopAsm(index) return outStr
elif ';' in cInst: # must be a jump statement cList = cInst.split(';') comp, jump = cList[0], cList[1] cBin = self._getCInst(comp, 'null', jump) # store it in the code list self._codeList.append(cBin + '\n') # get and create a c-instruction with provided # asm codes def _getCInst(self, comp, dest, jump): return '111' + self._ht.compBin(comp) +\ self._ht.destBin(dest) +\ self._ht.jumpBin(jump) # main/executable section of the code if __name__ == '__main__': if len(sys.argv) != 2: sys.exit(".asm file path not provided") filePath = sys.argv[1] # check to see if valid asm was provided if (not fh.fileExists(filePath)) or \ (not fh.isAsmFile(filePath)): sys.exit("Incorrect .asm file path") asm = Assembler(filePath) asm.assemble()
def translate(self): # aseemble the code self.parse() # write assembled code to .hack file fh.writeAsmFile(self._filePath, self._codeList)
outStr = self._cf.writeConstantPushPopAsm(index) return outStr # getter method for codelist attribute def getCodeList(self): return self._codeList # main/executable section of the code if __name__ == '__main__': if len(sys.argv) != 2: sys.exit(".vm file path not provided") fileDir = sys.argv[1] # check to see if the directory is valid if not fh.dirExists(fileDir): sys.exit("Incorrect file directory!") # get the file paths for all vm files in directory filePaths = fh.getVmFiles(fileDir) # the cformatter object cf = CFormatter() # intialize the code list for each file codeList = [] # iterate over each file path for i, filePath in enumerate(filePaths): tr = Translator(filePath, cf) if i == 0: tr.handleInit()
def _error(self): fh.writeXMLFile(self._filePath, self._codeList) sys.exit(self._tk.token() + " " + types[self._tk.type()] + \ " not a valid jack grammar")
def compile(self): # start by compiling class self._handleClass() # write assembled code to xml file fh.writeXMLFile(self._filePath, self._codeList)
self._writeXML() self._write("<expressionList>\n") self._level += 1 while self._tk.token() != ')': if self._tk.token() == ',': self._writeXML() else: # handle param type or name self._handleExpression() # write closing bracket self._level -= 1 self._write("</expressionList>\n") self._writeXML() else: self._error() # main/executable section of the code if __name__ == '__main__': if len(sys.argv) != 2: sys.exit(".jack file path not provided") filePath = sys.argv[1] # check to see if valid jack file was provided if (not fh.fileExists(filePath)) or \ (not fh.isJackFile(filePath)): sys.exit("Incorrect .jack file path") cp = Analyzer(filePath) cp.compile()