class CompilationEngine: ############################################## Consructor ############################################ # Creates a new compilation engine # with the given input and output. # The next routine calles must be compileClass(). def __init__(self, inputLines, filePath): # input information self.lines = inputLines self.destFile = filePath # Grammar rules grammar = JackGrammar() self.subroutineDec = grammar.getSubroutineDec() self.subs = grammar.getSubs() self.varDecs = grammar.getVarDecs() self.statements = grammar.getStatements() self.terms = grammar.getTerms() self.unaryOp = grammar.getUnaryOp() self.op = grammar.getOp() self.classVarDec = grammar.getClassVarDec() # global variables self.currentToken = "" self.currentTokenType = "" self.currentLine = "" self.nextToken = "" self.nextTokenType = "" self.isSubroutine = False self.className = "" self.currentFuncionName = "" self.nArgs = 0 self.isRight = False self.had_else = False self.whileLabelIndex = 0 self.ifLabelIndex = 0 self.isConstructor = False self.isMethod = False self.isArray = False self.wasRightArray = False self.wasArgument = False # SymbolTable self.symbolTable = SymbolTable() # VMWriter self.vmwriter = VMWriter(filePath) ############################################## Compile Class ############################################## # Compiles a complete class. def CompileClass(self): self.compileClassHelper() # Grammar: # class className {classVarDec* subroutine*} def compileClassHelper(self): if (len(self.lines) == 0): return self.manageNextTranslation() if self.currentTokenType == "identifier": self.className = self.currentToken self.compileClassHelper() elif self.currentTokenType == "symbol": self.compileClassHelper() elif self.currentToken in self.classVarDec: self.compileClassVarDec() self.compileClassHelper() elif self.currentToken in self.subroutineDec: self.CompileSubroutineDec() self.compileClassHelper() elif self.currentToken == "class": self.compileClassHelper() ############################################## Compile ClassVarDec ############################################## def compileClassVarDec(self): kind = "" type = "" while (self.currentToken not in self.subroutineDec): kind = self.currentToken self.manageNextTranslation() type = self.currentToken self.manageNextTranslation() name = self.currentToken self.symbolTable.Define(name, type, kind) self.manageNextTranslation() while self.currentToken != ";": self.manageNextTranslation() name = self.currentToken self.symbolTable.Define(name, type, kind) self.manageNextTranslation() self.manageNextTranslation() if self.currentToken == "constructor": self.isConstructor = True self.compileSubroutineDecHelper() self.isMethod = False ############################################## Compile SubroutineDec ############################################## # Compiles a static declaration or a field declaration. def CompileSubroutineDec(self): self.compileSubroutineDecHelper() self.isMethod = False # Grammar: # 'constructor', 'function', 'method' # ('void' | type) subroutineName (parameterList) # subroutineBody def compileSubroutineDecHelper(self): if (len(self.lines) == 0): return self.checkNextToken() if self.nextToken == "}": return if self.currentToken == "method": self.isMethod = True if self.currentToken != ")": self.manageNextTranslation() if self.currentToken in self.subroutineDec: self.compileSubroutineDecHelper() elif self.currentToken in self.subs: self.compileSubroutineDecHelper() elif self.currentTokenType == "identifier": self.currentFuncionName = self.currentToken self.symbolTable.startSubroutine() self.compileSubroutineDecHelper() elif self.currentTokenType == "symbol": if self.currentToken == "(": self.compileParameterList() self.compileSubroutineDecHelper() elif self.currentToken == ")": self.getSubroutineBody() elif self.currentToken == ",": self.compileSubroutineDecHelper() ############################################## Compile SubroutineBody ############################################## def getSubroutineBody(self): self.subroutineBodyhelper() def subroutineBodyhelper(self): self.checkNextToken() if self.nextToken == "}": self.manageNextTranslation() return if self.currentToken == "}" and self.had_else: self.had_else = False return self.manageNextTranslation() if self.currentTokenType == "symbol": if self.currentToken == "{": self.compileVarDec() self.checkNextToken() self.subroutineBodyhelper() ############################################## Compile VarDec ############################################## # Compiles a var declaration. def compileVarDec(self): self.manageNextTranslation() if self.currentToken == "var": self.manageNextTranslation() type = self.currentToken self.varDecHelper(type) elif self.currentToken in self.statements: self.vmwriter.WriteFunction( self.className + "." + self.currentFuncionName, str(self.symbolTable.getSize())) if self.isConstructor: count = self.symbolTable.VarCount("field") self.vmwriter.writePush("constant", count) self.vmwriter.WriteCall("Memory.alloc", 1) self.vmwriter.writePop("pointer", 0) self.isConstructor = False elif self.isMethod: self.vmwriter.writePush("argument", 0) self.vmwriter.writePop("pointer", 0) self.compileStatements() def varDecHelper(self, type): self.manageNextTranslation() if self.currentToken in self.varDecs or self.currentTokenType in self.varDecs: self.symbolTable.Define(self.currentToken, type, "var") self.varDecHelper(type) elif self.currentTokenType == "symbol": if self.currentToken == ";": self.compileVarDec() else: self.varDecHelper(type) ############################################## Compile ParameterList ############################################## # Compiles a (possibly empty) parameter list, # not including the enclosing "()". def compileParameterList(self): if self.isMethod: self.symbolTable.Define("this", self.className, "argument") self.manageNextTranslation() if self.currentToken != ")": self.paramListHelper() def paramListHelper(self): if self.currentTokenType == "symbol": if self.currentToken == ",": self.manageNextTranslation() self.paramListHelper() else: type = self.currentToken if type != "Array": type = self.currentTokenType self.manageNextTranslation() varName = self.currentToken self.symbolTable.Define(varName, type, "arg") self.manageNextTranslation() self.checkNextToken() self.paramListHelper() ############################################## Compile Statements ############################################## # Compiles a sequence of statements, not including the enclosing "{}". def compileStatements(self): self.compileStatementsHelper() def compileStatementsHelper(self): if self.currentToken == "do": self.compileDo() self.manageNextTranslation() self.compileStatementsHelper() elif self.currentToken == "let": self.compileLet() if self.nextToken == ";": self.manageNextTranslation() self.manageNextTranslation() self.compileStatementsHelper() elif self.currentToken == "while": self.compileWhile() self.manageNextTranslation() self.compileStatementsHelper() elif self.currentToken == "if": saved = self.ifLabelIndex self.compileIf() self.checkNextToken() self.checkNextToken() if self.nextToken == "else": self.manageNextTranslation() self.vmwriter.WriteGoto("IF_END_LABEL" + str(saved)) self.vmwriter.WriteLabel("IF_FALSE_LABEL" + str(saved)) self.had_else = True self.compileIf() self.vmwriter.WriteLabel("IF_END_LABEL" + str(saved)) else: self.vmwriter.WriteLabel("IF_FALSE_LABEL" + str(saved)) self.checkNextToken() if self.currentToken == "{" or self.currentToken == "}": self.manageNextTranslation() self.checkNextToken() self.compileStatementsHelper() elif self.currentToken == "return": self.compileReturn() ############################################## Compile do ############################################## # Compiles a do statement. def compileDo(self): self.compileDoHelper() self.vmwriter.writePop("temp", 0) def compileDoHelper(self): self.compileTermHelper() self.manageNextTranslation() ############################################## Compile Let ############################################## # Compiles a let statement. def compileLet(self): self.checkNextToken() varName = self.nextToken self.isArray = False self.wasRightArray = False self.isRight = False self.compileLetHelper() type = self.symbolTable.TypeOf(varName) kind = self.symbolTable.KindOf(varName) if self.wasRightArray and type == "Array": self.vmwriter.writePop("temp", 0) self.vmwriter.writePop("pointer", 1) self.vmwriter.writePush("temp", 0) self.vmwriter.writePop("that", 0) self.isArray = False else: kind = self.symbolTable.KindOf(varName) if kind != "none": self.vmwriter.writePop(kind, self.symbolTable.IndexOf(varName)) def compileLetHelper(self): self.manageNextTranslation() savedName = self.currentToken self.manageNextTranslation() if self.currentToken == "[": self.CompileExpression() kind = self.symbolTable.KindOf(savedName) indx = self.symbolTable.IndexOf(savedName) if kind != "none": self.vmwriter.writePush(kind, indx) self.vmwriter.WriteArithmetic("add") self.manageNextTranslation() self.isArray = True self.wasRightArray = True self.manageNextTranslation() if self.currentToken != "=": self.manageNextTranslation() self.isRight = True self.CompileExpression() ############################################## Compile While ############################################## # Compiles a while statement. def compileWhile(self): self.compileWhileHelper() def compileWhileHelper(self): if self.currentTokenType == "keyword": self.manageNextTranslation() self.compileWhileHelper() elif self.currentTokenType == "symbol": if self.currentToken == "(": self.vmwriter.WriteLabel("WHILE_EXPRESSIONS" + str(self.whileLabelIndex)) self.CompileExpression() self.manageNextTranslation() self.vmwriter.WriteArithmetic("not") self.vmwriter.WriteIf("WHILE_END" + str(self.whileLabelIndex)) self.manageNextTranslation() self.compileWhileHelper() elif self.currentToken == "{": saved = self.whileLabelIndex self.manageNextTranslation() self.whileLabelIndex += 1 self.compileStatements() self.vmwriter.WriteGoto("WHILE_EXPRESSIONS" + str(saved)) self.vmwriter.WriteLabel("WHILE_END" + str(saved)) ############################################## Compile return ############################################## # Compiles a return statement. def compileReturn(self): self.checkNextToken() if self.nextToken != ";": self.CompileExpression() else: self.vmwriter.writePush("constant", 0) self.vmwriter.writeReturn() self.manageNextTranslation() ############################################## Compile If ############################################## # Compiles an if statement, posibly with a trailing else clause. def compileIf(self): self.compileIfHelper() def compileIfHelper(self): self.manageNextTranslation() if self.currentTokenType in "symbol": if self.currentToken == "(": self.CompileExpression() self.vmwriter.WriteIf("IF_TRUE_LABEL" + str(self.ifLabelIndex)) self.vmwriter.WriteGoto("IF_FALSE_LABEL" + str(self.ifLabelIndex)) self.vmwriter.WriteLabel("IF_TRUE_LABEL" + str(self.ifLabelIndex)) self.manageNextTranslation() self.compileIfHelper() elif self.currentToken == "{": self.ifLabelIndex += 1 self.manageNextTranslation() self.compileStatements() if self.currentToken == ";": self.manageNextTranslation() ############################################## Compile Expression ############################################## # Compiles an expression. def CompileExpression(self): self.compileExpressionHelper() def compileExpressionHelper(self): self.CompileTerm() self.checkNextToken() if self.nextToken in self.op: self.manageNextTranslation() saved = self.currentToken self.compileExpressionHelper() if saved == "<": self.vmwriter.WriteArithmetic("lt") elif saved == ">": self.vmwriter.WriteArithmetic("gt") elif saved == "+": self.vmwriter.WriteArithmetic("add") elif saved == "-": self.vmwriter.WriteArithmetic("sub") elif saved == "*": self.vmwriter.WriteCall("Math.multiply", 2) elif saved == "/": self.vmwriter.WriteCall("Math.divide", 2) elif saved == "=": self.vmwriter.WriteArithmetic("eq") elif saved == "|": self.vmwriter.WriteArithmetic("or") elif saved == "&": self.vmwriter.WriteArithmetic("and") elif self.nextToken == ",": self.manageNextTranslation() ############################################## Compile term ############################################## def CompileTerm(self): self.compileTermHelper() if self.currentToken in self.unaryOp: saved = self.currentToken self.CompileTerm() if saved == "-": self.vmwriter.WriteArithmetic("neg") else: self.vmwriter.WriteArithmetic("not") self.isSubroutine = False # subName className varName def compileTermHelper(self): self.manageNextTranslation() if self.currentToken in self.terms or self.currentTokenType in self.terms: if self.currentTokenType == "integerConstant": self.vmwriter.writePush("constant", self.currentToken) elif self.currentTokenType == "stringConstant": self.vmwriter.writePush("constant", len(self.currentToken)) self.vmwriter.WriteCall("String.new", 1) for ch in self.currentToken: self.vmwriter.writePush("constant", ord(ch)) self.vmwriter.WriteCall("String.appendChar", 2) elif self.currentTokenType == "keyword": if self.currentToken == "null": self.vmwriter.writePush("constant", 0) elif self.currentToken == "true": self.vmwriter.writePush("constant", 0) self.vmwriter.WriteArithmetic("not") elif self.currentToken == "false": self.vmwriter.writePush("constant", 0) elif self.currentToken == "this": self.vmwriter.writePush("pointer", 0) elif self.currentTokenType == "identifier": if self.isSubroutine: varName = self.currentToken kind = self.symbolTable.KindOf(varName) else: self.checkNextToken() if self.nextToken == ";": kind = self.symbolTable.KindOf(self.currentToken) indx = self.symbolTable.IndexOf(self.currentToken) self.vmwriter.writePush(kind, indx) return if self.nextTokenType == "symbol" and self.nextToken != ".": varName = self.currentToken kind = self.symbolTable.KindOf(varName) if kind == "none": self.vmwriter.writePush("pointer", 0) self.isSubroutine = True self.compileTermHelper() self.vmwriter.WriteCall( self.className + "." + varName, self.nArgs + 1) return self.currentFuncionName = self.currentToken self.isSubroutine = True self.checkNextToken() savedName = self.currentToken savednxt = self.nextToken self.checkNextToken() if savednxt not in self.op and self.nextToken != ")" and self.nextToken != "]" and self.nextToken != "(": self.manageNextTranslation() if self.currentToken == "[": self.CompileExpression() if not self.isRight: self.wasRightArray = True self.isArray = True self.manageNextTranslation() if self.symbolTable.KindOf(savedName) != "none": self.vmwriter.writePush( self.symbolTable.KindOf(savedName), self.symbolTable.IndexOf(savedName)) kind = self.symbolTable.KindOf(self.currentToken) if kind == "argument": self.wasArgument = True if self.isArray and not self.wasArgument and not self.isSubroutine: if self.isRight: self.isArray = False self.vmwriter.WriteArithmetic("add") self.vmwriter.writePop("pointer", 1) self.vmwriter.writePush("that", 0) if self.currentToken == ".": saved = savedName self.manageNextTranslation() toWrite = self.currentFuncionName + "." + self.currentToken savedCurrent = self.currentToken self.compileTermHelper() type = self.symbolTable.TypeOf(savedCurrent) if type == "none": type = self.symbolTable.TypeOf(saved) if type == "none": # function self.vmwriter.WriteCall(toWrite, self.nArgs) else: kind = self.symbolTable.TypeOf(savedCurrent) indx = self.symbolTable.IndexOf(savedCurrent) if kind != "none": self.vmwriter.writePush(kind, indx) self.currentFuncionName = type saved = self.symbolTable.TypeOf(saved) toWrite = saved + "." + savedCurrent self.nArgs += 1 self.vmwriter.WriteCall(toWrite, self.nArgs) if self.nextToken not in ["[", "(", "."]: return self.compileTermHelper() if self.currentTokenType == "symbol": if self.currentToken == "(": if self.isSubroutine == True: self.nArgs = 0 self.CompileExpressionList() self.isSubroutine = False else: self.CompileExpression() self.manageNextTranslation() ############################################## Compile ExpressionList ############################################## # Compiles a (possibly empty) comma-separated # list of expressions. def CompileExpressionList(self): self.checkNextToken() if self.nextToken in self.unaryOp: self.CompileExpression() return self.checkNextToken() while self.nextToken != ")": self.nArgs += 1 self.CompileExpression() ############################################## Some Helper Functions ############################################## # updates next token (token itself and its type) # without removing from general list def checkNextToken(self): toCheck = self.lines[0] type = toCheck[1:toCheck.find(">")] startIndx = toCheck.find(">") + 2 endIndx = toCheck.find("<", startIndx) - 1 token = toCheck[startIndx:endIndx] self.nextToken = token self.nextTokenType = type # removes next token from general list # and updates information about current token def manageNextTranslation(self): toTranslate = self.lines.pop(0) self.currentLine = toTranslate type = toTranslate[1:toTranslate.find(">")] startIndx = toTranslate.find(">") + 2 endIndx = toTranslate.find("<", startIndx) - 1 token = toTranslate[startIndx:endIndx] self.currentToken = token self.currentTokenType = type
class CompilationEngine: def __init__(self, tokenizer, outputFile): self.XMLCode = [] self.CodeIndent = 0 self.tokenizer = tokenizer self.symbolTable = SymbolTable() self.vmWriter = VMWriter(outputFile) self.class_name = None self.segment_local_dict = segment_dict self.while_count = 0 self.if_count = 0 def nextToken(self): "advancing and retreiving the next token by Tokenizer" self.tokenizer.advance() current_token = self.tokenizer.getCurrentToken() token_type = self.tokenizer.typeOfToken() return current_token, token_type def compileToken(self, token): current_token, token_type = self.nextToken() self.compileLine(current_token, token_type) return current_token def compileTitle(self, title_name, isEntered): self.XMLCode.append(self.writeXMLCodeTitle(title_name, isEntered)) def compileLine(self, current_token, token_type): self.XMLCode.append(self.writeXMLCodeLine(current_token, token_type)) def writeXMLCodeLine(self, token_to_write, type_of_token): """writes into XML line all sorts of tokens which are not title @:param token_to_write: the current token to write @:param type_of_token: the current's token's type @:return: the XML code line""" return " " * self.CodeIndent + "<" + str( type_of_token) + ">" + " " + token_to_write.lstrip( ) + " " + "</" + str(type_of_token) + ">" def writeXMLCodeTitle(self, type_of_token, isEntered): """writes into XML line all sorts of tokens which are titles @:param isEntered: a boolean parameter implies if the current token is already opened if it is the token's first occurance isEntered== True, and False otherwise @:param type_of_token: the current's token's type @:return: the XML code line""" if isEntered == True: #if the title is opening myLine = " " * self.CodeIndent + "<" + str(type_of_token) + ">" self.CodeIndent += 2 #indent the lines of all other tokens within the current_token's scope return myLine else: #if isEntered == False we have to close the title token self.CodeIndent -= 2 myLine = " " * self.CodeIndent + "</" + str(type_of_token) + ">" return myLine def compileIdentifier(self, isClass=False): current_token, token_type = self.nextToken() if isClass: self.class_name = current_token # i've changed it because it was swapped self.XMLCode.append(self.writeXMLCodeLine(current_token, token_type)) return current_token def compileClass(self): self.compileTitle("class", True) self.compileToken( "class" ) # increnmenting the tokenizer and checking if the current token is indeed a class declaration self.compileIdentifier(True) self.compileToken("{") current_token, token_type = self.nextToken() while current_token in ["field", "static"]: self.compileClassVarDeclaration(current_token, token_type) current_token, token_type = self.nextToken() while current_token in ["constructor", "function", "method"]: self.compilesubRoutineDec(current_token, token_type) current_token, token_type = self.nextToken() self.compileToken("}") self.compileTitle("class", False) return self.XMLCode def compileClassVarDeclaration(self, current_token, token_type): #self.compileTitle("classVarDec",True) # first opening a new class title in XML #self.compileLine(current_token,token_type) VarKind = self.tokenizer.getCurrentToken() current_token, token_type = self.nextToken() VarType = current_token #self.compileType(current_token, token_type) VarName = self.compileIdentifier() self.symbolTable.define(VarName, VarType, VarKind) current_token, token_type = self.nextToken() while current_token == ",": # also the validation itself so no need of compile token self.compileLine(current_token, token_type) VarName = self.compileIdentifier() self.symbolTable.define(VarName, VarType, VarKind) current_token, token_type = self.nextToken() self.compileLine(current_token, token_type) self.compileTitle("classVarDec", False) def compileType(self, current_token, token_type): if current_token in ["int", "char", "boolean", self.class_name]: self.compileLine(current_token, token_type) else: self.compileLine(current_token, token_type) return current_token def compilesubRoutineDec(self, current_token, token_type): self.symbolTable.startSubroutine() self.if_count = 0 self.while_count = 0 #self.compileTitle("subroutineDec", True) #self.compileLine(current_token, token_type) func_type = self.tokenizer.getCurrentToken() current_token, token_type = self.nextToken() return_type = current_token if current_token in ["int", "char", "boolean", self.class_name ] or current_token == "void": self.compileLine(current_token, token_type) func_name = self.compileIdentifier() self.symbolTable.set_functionName(func_name, self.class_name) self.symbolTable.setFuncType(func_type) self.symbolTable.setReturnType(return_type) if func_type == "method": self.symbolTable.define("this", return_type, "arg") self.compileToken("(") self.compileParameterList() self.compileLine(")", "symbol") self.compileSubroutineBody() self.compileTitle("subroutineDec", False) def compileParameterList(self): self.compileTitle("parameterList", True) current_token, token_type = self.nextToken() while current_token != ")": VarType = self.compileType(current_token, token_type) VarName = self.compileIdentifier() self.symbolTable.define(VarName, VarType, "arg") current_token, token_type = self.nextToken() if current_token == ",": self.compileLine(current_token, token_type) current_token, token_type = self.nextToken() self.compileTitle("parameterList", False) def compileSubroutineBody(self): #self.compileTitle("subroutineBody", True)# first opening a new subroutineBody title in XML self.compileToken("{") current_token = self.tokenizer.showNextToken() while current_token == "var": self.compilevarDec() current_token = self.tokenizer.showNextToken() self.vmWriter.writeFunction(self.symbolTable.function_name, str(self.symbolTable.VarCount("var"))) # check wether the function type is method or constructor /*todo*/ if self.symbolTable.function_type == "method": self.vmWriter.writePush("argument", "0") self.vmWriter.writePop("pointer", "0") if self.symbolTable.function_type == "constructor": #slide 6 (7:00) about constructors field_num = self.symbolTable.VarCount("field") self.vmWriter.writePush("constant", str(field_num)) self.vmWriter.writeCall("Memory.alloc", "1") self.vmWriter.writePop("pointer", "0") current_token, token_type = self.nextToken() self.compileStatements(current_token, token_type) #self.compileLine("}","symbol") #self.compileTitle("subroutineBody", False) def compilevarDec(self): #self.compileTitle("varDec", True) current_token, token_type = self.nextToken() VarKind = "var" current_token, token_type = self.nextToken() VarType = current_token current_token, token_type = self.nextToken() VarName = current_token self.symbolTable.define(VarName, VarType, VarKind) #self.compileLine(current_token, token_type) current_token, token_type = self.nextToken() while current_token == ",": #self.compileLine(current_token, token_type) VarName = self.compileIdentifier() self.symbolTable.define(VarName, VarType, VarKind) current_token, token_type = self.nextToken() #self.compileLine(";", "symbol") #self.compileTitle("varDec", False) def compileStatements(self, current_token, token_type): self.compileTitle("statements", True) while current_token != "}": if current_token == "let": self.compileLet() elif current_token == "if": self.compileIf() elif current_token == "while": self.compileWhile() elif current_token == "do": self.compileDo() elif current_token == "return": self.compileReturn() current_token, token_type = self.nextToken() self.compileTitle("statements", False) def compileLet(self): self.compileTitle("letStatement", True) self.compileLine("let", "keyword") current_token, token_type = self.nextToken() temp = current_token # saves the new local variable current_token, token_type = self.nextToken() if current_token == "[": # if the left side is array self.compileLine("[", "symbol") self.compileExpression() self.compileLine("]", "symbol") var_memory_segment = self.segment_local_dict[ self.symbolTable.KindOf(temp)] #the kind of current var var_index = self.symbolTable.IndexOf(temp) self.vmWriter.writePush(var_memory_segment, str(var_index)) self.vmWriter.WriteArithmetic( "add" ) #if the left side is an array - add the index to get the value self.nextToken() #self.compileLine("=","symbol") self.compileExpression() #self.compileLine(";", "symbol") #self.compileTitle("letStatement", False) var_kind = self.symbolTable.KindOf(temp) var_type = self.symbolTable.TypeOf(temp) index_segment = self.symbolTable.IndexOf(temp) kind_seg = self.segment_local_dict[var_kind] if current_token == "[" and kind_seg in ["local", "argument"]: #slide 8 (20:00) !!! self.vmWriter.writePop("temp", "0") self.vmWriter.writePop("pointer", "1") self.vmWriter.writePush("temp", "0") self.vmWriter.writePop("that", "0") else: #if the first var was not an Arrayso just pop the value from the expression to it self.vmWriter.writePop(kind_seg, str(index_segment)) def compileIf(self): #self.compileTitle("ifStatement", True) #self.compileLine("if", "keyword") self.compileToken("(") self.compileExpression() self.compileLine(")", "symbol") if_true_label = "TRUE" + str( self.if_count) #define true and false labels!! if_false_label = "FALSE" + str(self.if_count) end_if_label = "END" + str(self.if_count) self.if_count += 1 self.vmWriter.WriteIf( if_true_label ) # after pushing to stack the expression write labels self.vmWriter.WriteGoto(if_false_label) self.compileToken("{") self.vmWriter.WriteLabel( if_true_label ) # put the TRUE_LABEL at the begining of the if clause current_token, token_type = self.nextToken() self.compileStatements(current_token, token_type) #self.compileLine("}","symbol") #check if there is "else" statement temp = self.tokenizer.showNextToken() if temp == "else": #put the END_LABEL and put the False_label If the condionn not true self.vmWriter.WriteGoto(end_if_label) self.vmWriter.WriteLabel(if_false_label) current_token, token_type = self.nextToken() #self.compileLine("else","keyword") self.compileToken("{") current_token, token_type = self.nextToken() self.compileStatements(current_token, token_type) self.vmWriter.WriteLabel(end_if_label) #self.compileLine("}","symbol") else: self.vmWriter.WriteLabel(if_false_label) #self.compileTitle("ifStatement", False) def compileWhile(self): #self.compileTitle("whileStatement", True) #self.compileLine("while", "keyword") while_start_label = "STRAT" + str( self.while_count) # defining astart and stop labels!! while_end_label = "END" + str(self.while_count) self.while_count += 1 self.vmWriter.WriteLabel(while_start_label) self.compileToken("(") self.compileExpression() #self.compileLine(")","symbol") #negating the boolean expression and check whether to enter or not self.vmWriter.WriteArithmetic("not") self.vmWriter.WriteIf(while_end_label) self.compileToken("{") current_token, token_type = self.nextToken() self.compileStatements(current_token, token_type) self.vmWriter.WriteGoto(while_start_label) self.vmWriter.WriteLabel(while_end_label) #self.compileLine("}", "symbol") #self.compileTitle("whileStatement", False) def compileDo(self): #self.compileTitle("doStatement", True) #self.compileLine("do", "keyword") self.compileSubroutineCall() self.vmWriter.writePop("temp", "0") self.nextToken() #self.nextToken() #self.compileLine(";","symbol") #self.compileTitle("doStatement", False) def compileReturn(self): #self.compileTitle("returnStatement", True) #self.compileLine("return", "keyword") if self.symbolTable.return_type == "void": self.vmWriter.writePush("constant", "0") # always push 0 to the stack!! temp = self.tokenizer.showNextToken() while not temp == ";": self.nextToken() temp = self.tokenizer.showNextToken() else: temp = self.tokenizer.showNextToken() if temp != ";": self.compileExpression() else: self.vmWriter.writePush("constant", "0") self.vmWriter.writeReturn() #self.compileLine(";","symbol") #self.compileTitle("returnStatement", False) def compileExpression(self): #self.compileTitle("expression", True) self.compileTerm() current_token, token_type = self.nextToken() while current_token in op: self.compileLine(current_token, token_type) self.compileTerm() self.vmWriter.WriteArithmetic( current_token ) # after two expression/terms we will write arithmetic current_token, token_type = self.nextToken() self.compileTitle("expression", False) def compileExpressionList(self): num_of_args = 0 self.compileTitle("expressionList", True) current_token = self.tokenizer.showNextToken() if current_token != ")": self.compileExpression() num_of_args += 1 # add the first parameter found inside paranthesis( ) while (self.tokenizer.getCurrentToken() == ","): num_of_args += 1 self.compileLine(",", "symbol") self.compileExpression() if current_token == ")": self.nextToken() self.compileTitle("expressionList", False) return num_of_args def compileTerm(self): #self.compileTitle("term", True) current_token, token_type = self.nextToken() kind = self.symbolTable.KindOf(current_token) temp = self.tokenizer.showNextToken() if token_type == "int_constant": # self.compileLine(current_token,"integerConstant") self.vmWriter.writePush("constant", str(current_token)) elif kind == "var" and temp != "[" and temp != ".": self.vmWriter.writePush( "local", str(self.symbolTable.IndexOf(current_token))) elif kind == "arg" and current_token != "this": self.vmWriter.writePush( "argument", str(self.symbolTable.IndexOf(current_token))) elif token_type == "string_constant": #self.compileLine(current_token.strip("\""),"stringConstant") string_constant = current_token.strip("\"") string_lenth = len(string_constant) self.vmWriter.writePush("constant", str(string_lenth)) self.vmWriter.writeCall("String.new", 1) #now getting the numerical value of each char in the string and append them for char in string_constant: self.vmWriter.writePush("constant", str(ord(char))) self.vmWriter.writeCall("String.appendChar", "2") elif kind == "static" and temp != "." and temp != "[": self.vmWriter.writePush( "static", str(self.symbolTable.IndexOf(current_token))) elif kind == "field" and temp != "." and temp != "]": self.vmWriter.writePush( "this", str(self.symbolTable.IndexOf(current_token))) elif current_token in [ "true", "false", "null", "this" ]: # not the kind it only means that the tokens itself is one of them #self.compileLine(current_token,token_type) #its a keyword! if current_token == "true": self.vmWriter.writePush("constant", "0") self.vmWriter.WriteArithmetic("not") elif current_token == "this": self.vmWriter.writePush("pointer", "0") else: # its false or null self.vmWriter.writePush("constant", "0") # if its ( expression ) elif current_token == "(": self.compileLine(current_token, token_type) self.compileExpression() self.compileLine(")", "symbol") #if its Unary Op elif current_token in ["~", "-"]: self.compileLine(current_token, token_type) self.compileTerm() if current_token == "~": self.vmWriter.WriteArithmetic("not") else: self.vmWriter.WriteArithmetic("neg") #if its varName [ expression ] elif token_type == "identifier" and temp != ".": # maybe add and temp != ";" ???????? self.compileLine(current_token, token_type) if temp == "[": self.compileLine(temp, "symbol") var_name = current_token current_token, token_type = self.nextToken() self.compileExpression() self.compileLine("]", "symbol") var_memory_segment = self.segment_local_dict[ self.symbolTable.KindOf( var_name)] # the kind of current var var_index = self.symbolTable.IndexOf(var_name) self.vmWriter.writePush(var_memory_segment, str(var_index)) self.vmWriter.WriteArithmetic( "add") # if the left side is an array self.vmWriter.writePop("pointer", "1") self.vmWriter.writePush("that", "0") # subroutine elif token_type == "identifier" and temp in ["(", "."]: self.tokenizer.previousToken() self.compileSubroutineCall() # if its a var_name elif token_type == "identifier" and not temp in ["[", "(", "."]: var_name = current_token var_memory_segment = self.segment_local_dict[ self.symbolTable.KindOf(var_name)] # the kind of current var var_index = self.symbolTable.IndexOf(var_name) self.vmWriter.writePush(var_memory_segment, str(var_index)) self.compileTitle("term", False) def compileSubroutineCall(self): num_of_args = 0 func_name = self.compileIdentifier( ) # func_name first contain the class name current_token, token_type = self.nextToken() if current_token == ".": var_kind = self.symbolTable.KindOf(func_name) var_index = self.symbolTable.IndexOf(func_name) var_type = self.symbolTable.TypeOf(func_name) if var_type != False: # enter only if it is a method called by an object num_of_args += 1 # num of arguments of a method starts from 1 because of the "self" argument func_name = var_type mem_segment = self.segment_local_dict[var_kind] self.vmWriter.writePush( mem_segment, str(var_index) ) # push memory segment to stack be calling function func_name += "." func_name += self.compileIdentifier() #self.compileLine(".", "symbol") self.compileToken("(") num_of_args += self.compileExpressionList() self.compileLine(")", "symbol") self.vmWriter.writeCall(func_name, str(num_of_args)) else: self.vmWriter.writePush("pointer", "0") num_of_args += 1 func_name = self.class_name + "." + func_name self.compileLine("(", "symbol") num_of_args += self.compileExpressionList() self.compileLine(")", "symbol") self.vmWriter.writeCall(func_name, str(num_of_args))