def __init__(self, jackTokenizer): self.jackTokenizer = jackTokenizer self.symbolTabel = SymbolTabel() self.vmWriter = VMWriter() self.result = [] self.labelCount = 0 #用来解决不同if等等语句中相同label的问题 self.fieldCount = 0 self.compileClass()
class CompilationEngine(): def __init__(self, jackTokenizer): self.jackTokenizer = jackTokenizer self.symbolTabel = SymbolTabel() self.vmWriter = VMWriter() self.result = [] self.labelCount = 0 #用来解决不同if等等语句中相同label的问题 self.fieldCount = 0 self.compileClass() def __getFieldNums(self): #获取一个对象中的成员变量的数量, 以便构造函数编译时分配空间, 增量代码在compileClassVarDec中 return self.fieldCount def __getLocalNums(self): #用来解决function name n 的参数问题 pointer = self.jackTokenizer.pointer+1 n = 0 while(self.jackTokenizer.context[pointer]=="var"): n += 1 pointer += 3 while(self.jackTokenizer.context[pointer]!=";"): pointer += 2 n += 1 pointer += 1 return n def __match(self, label): self.jackTokenizer.advance() def __getAndAdvanceLabel(self): self.labelCount += 1 return str(self.labelCount) def __getToken(self): return self.jackTokenizer.getToken() def __getTokenType(self): return self.jackTokenizer.tokenType() def __getFurtureToken(self, n): return self.jackTokenizer.context[self.jackTokenizer.pointer+n] def __getPastToken(self, n): return self.jackTokenizer.context[self.jackTokenizer.pointer-n] def compileClass(self): self.__match("class") self.__match("className") self.__match("{") while(self.__getToken()=="static" or self.__getToken()=="field"): self.compileClassVarDec() while(self.__getToken()=="constructor" or self.__getToken()=="function" or self.__getToken()=="method"): self.symbolTabel.startSubroutine() #子程序的符号表重启 self.compileSubroutineDec() self.__match("}") def compileClassVarDec(self): kind = self.__getToken() self.__match("static|field") typE = self.__getToken() self.__match("type") name = [] name.append(self.__getToken()) self.__match("varName") while(self.__getToken()!=";"): if(self.__getToken()==","): self.__match(",") else: name.append(self.__getToken()) self.__match("varName") self.__match(";") if(kind=="field"): self.fieldCount += len(name) for i in name: self.symbolTabel.define(i, typE, kind) def compileSubroutineDec(self): kind = self.__getToken() self.__match("constructor|function|method") typE = self.__getToken() self.__match("void|type") functionName = self.__getToken() self.__match("subroutineName") self.__match("(") self.compileParameterList() self.__match(")") n = self.__getLocalNums() self.vmWriter.writeFunction(self.jackTokenizer.context[1]+"."+functionName, str(n)) if(kind=="constructor"): self.vmWriter.writePush("constant", str(self.__getFieldNums())) self.vmWriter.writeCall("Memory.alloc", "1") self.vmWriter.writePop("pointer", "0") elif(kind=="method"): #将this指向传入的对象 self.vmWriter.writePush("argument", "0") self.vmWriter.writePop("pointer", "0") self.compileSubroutineBody() def compileSubroutineBody(self): self.__match("{") while(self.__getToken()=="var"): self.compileVarDec() self.compileStatements() self.__match("}") def compileStatements(self): tmp = ["let", "if", "while", "do", "return"] while(self.__getToken() in tmp): if(self.__getToken() == "while"): self.compileWhileStatement() elif(self.__getToken() == "if"): self.compileIfStatement() elif(self.__getToken() == "return"): self.compileReturnStatement() elif(self.__getToken() == "let"): self.compileLetStatement() else: self.compileDoStatement() def compileDoStatement(self): #do后面跟的必定是void类型的函数或方法 self.__match("do") name = "" n = 0 if(self.__getFurtureToken(1)=="."): prefix = self.__getToken() self.__match("className|varName") self.__match(".") name = self.__getToken() self.__match("subroutineName") if(self.symbolTabel.kindOf(prefix)!="none"): #varName.method n += 1 #调用method, 所以要把对象的指针push进去 if(self.symbolTabel.kindOf(prefix)=="field"): self.vmWriter.writePush("this", self.symbolTabel.indexOf(prefix)) elif(self.symbolTabel.kindOf(prefix)=="var"): self.vmWriter.writePush("local", self.symbolTabel.indexOf(prefix)) elif(self.symbolTabel.kindOf(prefix)=="argument"): self.vmWriter.writePush("argument", self.symbolTabel.indexOf(prefix)) elif(self.symbolTabel.kindOf(prefix)=="static"): self.vmWriter.writePush("static", self.symbolTabel.indexOf(prefix)) name = self.symbolTabel.typeOf(prefix)+"."+name else: #className.function name = prefix+"."+name self.__match("(") n += self.compileExpressionList() self.__match(")") else: #do method() name = self.jackTokenizer.context[1]+"."+self.__getToken() self.__match("subroutineName") self.vmWriter.writePush("pointer", "0") self.__match("(") n = self.compileExpressionList() n += 1 #对象的方法 self.__match(")") self.__match(";") self.vmWriter.writeCall(name, str(n)) self.vmWriter.writePop("temp", "0") def compileLetStatement(self): isArray = False self.__match("let") name = self.__getToken() self.__match("varName") if(self.__getToken()=="["): isArray = True self.__match("[") self.compileExpression() self.__match("]") self.__match("=") self.compileExpression() self.__match(";") #以下为代码生成 if(isArray==True): self.vmWriter.writePop("temp", "0") # "="右边的值 kind = self.symbolTabel.kindOf(name) index = self.symbolTabel.indexOf(name) if(kind=="field"): #把数组的指针push进去, 现在栈顶是指针和偏移值 self.vmWriter.writePush("this", str(index)) elif(kind=="argument"): self.vmWriter.writePush("argument", str(index)) elif(kind=="var"): self.vmWriter.writePush("local", str(index)) elif(kind=="static"): self.vmWriter.writePush("static", str(index)) self.vmWriter.writeArithmetic("add") self.vmWriter.writePop("pointer", "1") self.vmWriter.writePush("temp", "0") self.vmWriter.writePop("that", "0") else: kind = self.symbolTabel.kindOf(name) index = self.symbolTabel.indexOf(name) if(kind=="field"): self.vmWriter.writePop("this", index) elif(kind=="argument"): self.vmWriter.writePop("argument", index) elif(kind=="var"): self.vmWriter.writePop("local", index) elif(kind=="static"): self.vmWriter.writePop("static", index) def compileWhileStatement(self): label = self.__getAndAdvanceLabel() self.__match("while") self.vmWriter.writeLabel("exp-examination"+label) self.__match("(") self.compileExpression() self.__match(")") self.vmWriter.writeIfGoto("loop"+label) self.vmWriter.writeGoto("end"+label) self.vmWriter.writeLabel("loop"+label) self.__match("{") self.compileStatements() self.__match("}") self.vmWriter.writeGoto("exp-examination"+label) self.vmWriter.writeLabel("end"+label) def compileIfStatement(self): label = self.__getAndAdvanceLabel() self.__match("if") self.__match("(") self.compileExpression() self.__match(")") self.vmWriter.writeIfGoto("true"+label) self.vmWriter.writeGoto("false"+label) self.vmWriter.writeLabel("true"+label) self.__match("{") self.compileStatements() self.__match("}") self.vmWriter.writeGoto("end"+label) self.vmWriter.writeLabel("false"+label) if(self.__getToken()=="else"): self.__match("else") self.__match("{") self.compileStatements() self.__match("}") self.vmWriter.writeLabel("end"+label) def compileReturnStatement(self): self.__match("return") if(self.__getToken()!=";"): self.compileExpression() else: #return; self.vmWriter.writePush("constant", "0") self.vmWriter.writeReturn() self.__match(";") def compileVarDec(self): kind = "var" self.__match("var") typE = self.__getToken() self.__match("type") name = [] name.append(self.__getToken()) self.__match("name") while(self.__getToken()!=";"): if(self.__getToken()==","): self.__match(",") name.append(self.__getToken()) self.__match("name") self.__match(";") for i in name: self.symbolTabel.define(i, typE, kind) def compileParameterList(self): kind = "argument" typE = [] name = [] if(self.__getPastToken(4)=="method"): #对于方法, 第一个参数是对象的指针 typE.append(self.jackTokenizer.context[1]) #className name.append("this") while(self.__getToken()!=")"): typE.append(self.__getToken()) self.__match("type") name.append(self.__getToken()) self.__match("varName") if(self.__getToken()==","): self.__match(",") for i,j in zip(name,typE): self.symbolTabel.define(i, j, kind) def compileExpression(self): #遇到op就放到term后面压栈, term求值之后压栈, expression求值之后压栈 op = ["+", "-", "*", "/", "&", "|", "<", ">", "="] self.compileTerm() while(self.__getToken() in op): tmp_op = self.__getToken() self.__match("op") self.compileTerm() #压入运算符 if(tmp_op=="*"): self.vmWriter.writeCall("Math.multiply", "2") elif(tmp_op=="+"): self.vmWriter.writeArithmetic("add") elif(tmp_op=="-"): self.vmWriter.writeArithmetic("sub") elif(tmp_op=="/"): self.vmWriter.writeCall("Math.divide", "2") elif(tmp_op=="&"): self.vmWriter.writeArithmetic("and") elif(tmp_op=="|"): self.vmWriter.writeArithmetic("or") elif(tmp_op=="<"): self.vmWriter.writeArithmetic("lt") elif(tmp_op==">"): self.vmWriter.writeArithmetic("gt") elif(tmp_op=="="): self.vmWriter.writeArithmetic("eq") def compileTerm(self): keywordConstant = ["true", "false", "null", "this"] unaryOp = ["-", "~"] if(self.__getTokenType()=="integerConstant"): self.vmWriter.writePush("constant", self.__getToken()) self.__match("integerConstant") elif(self.__getTokenType()=="stringConstant"): string = self.__getToken() string = string.replace('"', "") self.__match("string") #申请空间 self.vmWriter.writePush("constant", str(len(string))) self.vmWriter.writeCall("String.new", "1") #调用String.appendChar <- method, 接收一个char, 返回一个字符串的地址) for i in string: self.vmWriter.writePush("constant", str(ord(i))) self.vmWriter.writeCall("String.appendChar", "2") elif(self.__getToken() in keywordConstant): tmp = self.__getToken() if(tmp=="null"): self.vmWriter.writePush("constant", "0") elif(tmp=="false"): self.vmWriter.writePush("constant", "0") elif(tmp=="true"): self.vmWriter.writePush("constant", "1") self.vmWriter.writeArithmetic("neg") elif(tmp=="this"): self.vmWriter.writePush("pointer", "0") self.__match("keywordConstant") elif(self.__getToken()=="("): #(expression) self.__match("(") self.compileExpression() self.__match(")") elif(self.__getToken() in unaryOp): #unaryOp term tmp_uop = self.__getToken() self.__match("unaryOp") self.compileTerm() if(tmp_uop=="-"): self.vmWriter.writeArithmetic("neg") elif(tmp_uop=="~"): label = self.__getAndAdvanceLabel() self.vmWriter.writeIfGoto("true"+label) self.vmWriter.writeGoto("false"+label) self.vmWriter.writeLabel("true"+label) self.vmWriter.writePush("constant", "0") self.vmWriter.writeGoto("end"+label) self.vmWriter.writeLabel("false"+label) self.vmWriter.writePush("constant", "1") self.vmWriter.writeArithmetic("neg") self.vmWriter.writeLabel("end"+label) elif(self.__getFurtureToken(1)=="["): #varName[expression] name = self.__getToken() typE = self.symbolTabel.typeOf(name) kind = self.symbolTabel.kindOf(name) index = self.symbolTabel.indexOf(name) if(kind=="field"): self.vmWriter.writePush("this", str(index)) elif(kind=="var"): self.vmWriter.writePush("local", str(index)) else: self.vmWriter.writePush(kind, str(index)) self.__match("varName") self.__match("[") self.compileExpression() self.__match("]") self.vmWriter.writeArithmetic("add") self.vmWriter.writePop("pointer", "1") self.vmWriter.writePush("that", "0") elif(self.__getFurtureToken(1)=="("): #subroutineName(expressionList) name = self.__getToken() name = self.jackTokenizer.context[1]+"."+self.__getToken() self.__match("subroutineCall") self.__match("(") n = self.compileExpressionList() n += 1 self.__match(")") self.vmWriter.writePush("pointer", "0") self.vmWriter.writeCall(name, str(n)) elif(self.__getFurtureToken(1)=="."): #(className|varName).subroutineName(expressionList) prefix = self.__getToken() self.__match("className|varName") self.__match(".") name = self.__getToken() self.__match("subroutineName") self.__match("(") n = self.compileExpressionList() self.__match(")") if(self.symbolTabel.kindOf(prefix)=="none"): #className name = prefix+"."+name self.vmWriter.writeCall(name, str(n)) else: #varName name = self.symbolTabel.typeOf(prefix)+"."+name n += 1 #调用method, 所以要把对象的指针push进去 if(self.symbolTabel.kindOf(prefix)=="field"): self.vmWriter.writePush("this", self.symbolTabel.indexOf(prefix)) elif(self.symbolTabel.kindOf(prefix)=="var"): self.vmWriter.writePush("local", self.symbolTabel.indexOf(prefix)) elif(self.symbolTabel.kindOf(prefix)=="argument"): self.vmWriter.writePush("argument", self.symbolTabel.indexOf(prefix)) elif(self.symbolTabel.kindOf(prefix)=="static"): self.vmWriter.writePush("static", self.symbolTabel.indexOf(prefix)) self.vmWriter.writeCall(name, str(n)) else: #varName name = self.__getToken() kind = self.symbolTabel.kindOf(name) index = self.symbolTabel.indexOf(name) if(kind=="field"): self.vmWriter.writePush("this", index) elif(kind=="var"): self.vmWriter.writePush("local", index) else: self.vmWriter.writePush(kind, index) self.__match("varName") def compileExpressionList(self): #返回expression的数量 n = 0 if(self.__getToken()!=")"): self.compileExpression() n += 1 while(self.__getToken()==","): self.__match(",") self.compileExpression() n += 1 return n def write(self, path): for i in range(len(self.result)): self.result[i] += "\n" with open(path, "w") as f: f.writelines(self.result)