Пример #1
0
 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()
Пример #2
0
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)