コード例 #1
0
def Return(token):

    if len(returnList):
        returnList[-1][2] = 1

    token = lexer.peekNextToken()
    if token[1] == ";" and token[0] == "symbol":
        lexer.getNextToken()  # consume the token
        # No value to be returned, just push const 0
        text("push constant 0")
        if lexer.peekNextToken()[1] != "}":
            Error(token, "Unreachable code")

    elif token[0] in ["id", "number"]:
        # Return expression
        returnData = symbolTable.orderExpr("return")
        if not returnData[0]:
            return returnData

    elif token[1] == "this":
        text("push pointer 0")

    else:
        Error(
            token,
            "Unexpected token of type '" + token[0] + "' cannot be returned.")

    text("return")
    return [1]
コード例 #2
0
def let(token):

    token = lexer.getNextToken()
    if token[0] != "id":
        return [0, "Expected 'id'"]

    peekToken = lexer.peekNextToken()
    if peekToken[1] == "[" and peekToken[0] == "symbol":  # Check if array

        expr = [token]  # Stores list of tokens in expression
        lexer.getNextToken()  # consume token
        expr[-1][0] = "array"
        expr[-1][1] = [copy.copy(expr[-1]),
                       []]  # store function with arguments
        bCount = 1
        while bCount:  # Exit on obtaining all parameters
            token = lexer.getNextToken()

            if token[1] == "[" and token[0] == "symbol":
                bCount += 1
            elif token[1] == "]" and token[0] == "symbol":
                bCount -= 1

            if bCount:
                expr[-1][1][1].append(token)

        token = lexer.peekNextToken()  # Revert peek

        symbolTable.arrayLetSwitch = 1
        symbolTable.expressionToCode(expr)
        symbolTable.arrayLetSwitch = 0

        getToken = lexer.getNextToken()
        if getToken[1] != "=" and getToken[0] != "operator":
            return [0, "Expected '='"]

        returnData = symbolTable.orderExpr("let")
        if not returnData[0]:
            return returnData

        text("pop temp 0")
        text("pop pointer 1")
        text("push temp 0")
        text("pop that 0")

    else:
        popData = symbolTable.pushPop(token)

        getToken = lexer.getNextToken()
        if getToken[1] != "=" and getToken[0] != "operator":
            return [0, "Expected '='"]

        returnData = symbolTable.orderExpr("let")
        if not returnData[0]:
            return returnData
        text("pop " + popData[0] + " " + str(popData[1]))

    return [1]
コード例 #3
0
def setObjectName():
    # Check function has appropriate type and name
    token = lexer.getNextToken()
    if token[0] != "id":
        Error(token, "Expected 'id'")

    # Reset counter and set new name on entry to new object
    symbolTable.objectName = token[1]
    symbolTable.labelCounter = [0, 0, 0]

    # Get number of declared variables in function
    while (token[1] != "{"):  # loop to start of function
        token = lexer.peekNextToken()
        if token[0] == "EOF":
            Error(token, "Unexpected EOF")

    # Loop to end of the function
    # Incriment variable counter each time one is encountered
    bCount = 1
    varCount = 0
    while bCount:
        token = lexer.peekNextToken()

        if token[1] == "var":
            token = lexer.peekNextToken()  # Consume data type

            # Check syntax of variables and add them to the symbol table
            tokenSwitch = 1  # Switch between checking for id and symbol with each loop
            while token[1] != ";":
                token = lexer.peekNextToken()

                if token[1] != ";":
                    if tokenSwitch:
                        if token[0] != "id":
                            Error(token, "Expected token of type 'identifier'")
                        else:
                            varCount += 1
                        tokenSwitch = 0
                    else:
                        if token[0] != "symbol" and token[1] != ",":
                            Error(token, "Expected ','")
                        else:
                            tokenSwitch = 1

                if token[0] == "EOF":
                    Error(token, "Unexpected EOF")

        if token[1] == "{":
            bCount += 1
        elif token[1] == "}":
            bCount -= 1

        if token[0] == "EOF":
            Error(token, "Unexpected EOF")

    text("function " + symbolTable.className + "." + symbolTable.objectName +
         " " + str(varCount))
コード例 #4
0
ファイル: Parser.py プロジェクト: AlistairArk/JACK-Compiler
def parseFile():
    # Generate a list of methods to later be used in function calls
    token = lexer.peekNextToken()
    while (token[0] != "EOF"):
        if token[1] == "method":
            lexer.peekNextToken()  # consume
            symbolTable.methodList.append(lexer.peekNextToken()[1])
        token = lexer.peekNextToken()

    # Begin main parsing of file
    token = lexer.getNextToken()
    while (token[0] != "EOF"):
        stmt(token)
        token = lexer.getNextToken()
コード例 #5
0
def setObjectArgs(attribute):

    # Log bracket count when entering a function so you can later tell when the function is exited
    #                       function name,           bracket pointer,    value returned
    returnList.append(
        [symbolTable.objectName, symbolTable.bracketPointer[0], 0])

    token = lexer.getNextToken()
    if token[1] != "(" and token[0] != "symbol":
        Error(token, "Expected '('")

    peekToken = lexer.peekNextToken()
    if peekToken[1] == ")" and peekToken[
            0] == "symbol":  # Check if function has no arguments
        lexer.getNextToken()  # Consume the token

    else:
        # Check syntax of function arguments
        expectedTypeList = [["keyword", "id"], ["id"], ["symbol"]]
        expectedTypePointer = 0
        while token[1] != ")":
            token = lexer.getNextToken()

            if token[0] not in expectedTypeList[expectedTypePointer]:

                Error(token, "Expected a type followed by a variable name")

            elif expectedTypePointer == 0:
                pass

            elif expectedTypePointer == 1:  # add variable to symbol table
                symbolTable.addSymbol(type="argument",
                                      attribute=attribute,
                                      symbol=token[1],
                                      scope="")

            elif expectedTypePointer == 2:
                if not token[1] in [",", ")"]:
                    Error(token, "Expected ')' or ',' in parameters list")

            # incriment pointer
            expectedTypePointer += 1
            if expectedTypePointer == 3:
                expectedTypePointer = 0

    token = lexer.peekNextToken()
    if token[1] != "{" and token[0] != "symbol":
        Error(token, "Expected '{'")

    return [1]
コード例 #6
0
def Else(token):

    peekToken = lexer.peekNextToken()
    if peekToken[1] != "{" and peekToken[0] != "symbol":
        Error(token, "Expected '{'")

    return [1]
コード例 #7
0
def Class(token):
    token = lexer.getNextToken()

    if token[0] != "id":
        Error(token, "Expected 'id'")
    else:
        symbolTable.className = token[1]

    if lexer.peekNextToken()[1] != "{":
        Error(token, "Expected '{'")

    return [1]
コード例 #8
0
def symbol(token):

    if token[1] == "{" and token[0] == "symbol":
        symbolTable.bracketPointer[0] += 1
    if token[1] == "}" and token[0] == "symbol":
        symbolTable.bracketPointer[0] -= 1

        # Verify last function exited has a return
        if len(returnList) and (symbolTable.bracketPointer[0]
                                == returnList[-1][1]):
            if not returnList[-1][2]:
                Error(
                    token, "In subroutine '" + returnList[-1][0] +
                    "': Program flow may reach end of subroutine without 'return'"
                )

        if not symbolTable.bracketPointer[0]:
            Error(token, "Mismatched number of braces")
        else:
            # Check stack to detect closing of if or while loop
            for item in symbolTable.labelStack:
                if item[1] == symbolTable.bracketPointer[0]:

                    # Check type
                    if item[2] == "while":
                        text("goto WHILE_EXP" + item[0])
                        text("label WHILE_END" + item[0])
                        symbolTable.labelStack.pop()
                    elif item[2] == "if":
                        symbolTable.labelStack.pop()

                        peekToken = lexer.peekNextToken()
                        if peekToken[1] == "else":
                            symbolTable.newLabel("else")
                            text("goto IF_END" + symbolTable.labelStack[-1][0])

                        text("label IF_FALSE" + item[0])

                    elif item[2] == "else":
                        text("label IF_END" + item[0])
                        symbolTable.labelStack.pop()

                    elif item[2] == "retun":
                        text("label IF_END" + item[0])
                        symbolTable.labelStack.pop()

    if token[1] == "(" and token[0] == "symbol":
        symbolTable.bracketPointer[1] += 1
    if token[1] == ")" and token[0] == "symbol":
        symbolTable.bracketPointer[1] -= 1
        if not symbolTable.bracketPointer[1]:
            Error(token, "Mismatched number of parenthesis")

    if token[1] == "[" and token[0] == "symbol":
        symbolTable.bracketPointer[2] += 1
    if token[1] == "]" and token[0] == "symbol":
        symbolTable.bracketPointer[2] -= 1
        if not symbolTable.bracketPointer[2]:
            Error(token, "Mismatched number of square brackets")

    return [1]
コード例 #9
0
def orderExpr(exprType):
    ''' Obtains a list of tokens which comprise an expression '''

    # Perform checks on the expression and wrap it up into a list
    bracketOpenCount = 0
    expr = []  # Stores list of tokens in expression
    token = lexer.peekNextToken()
    errorToken = token  # Hold current token for later error calls

    if exprType in ["if", "while"]:
        ending = "{"
    elif exprType in ["let", "do"]:
        ending = ";"
    elif exprType in ["return"]:
        ending = ";"
        token = [token[0], "return", token[2]]

    while token[1] != ending:

        token = lexer.getNextToken()  # Consume token
        if token[0] == "EOF":
            Error(errorToken, "Unexpected EOF")

        expr.append(token)

        # Insure matching number of parenthesis
        if token[0] == "symbol" and token[1] == "(":
            bracketOpenCount += 1
        elif token[0] == "symbol" and token[1] == ")":
            bracketOpenCount -= 1

        if bracketOpenCount == -1:
            Error(errorToken, "Mismatched number of parenthesis")

        lastToken = token
        token = lexer.peekNextToken()
        # Check if next token implies the current token is a function call
        if lastToken[0] == "id" and (token[1] == "(" and token[0] == "symbol"):
            lexer.getNextToken()  # consume token
            expr[-1][0] = "function"
            expr[-1][1] = [copy.copy(expr[-1]),
                           []]  # store function with arguments
            bCount = 1
            while bCount:  # Exit on obtaining all parameters
                token = lexer.getNextToken()
                if token[1] == "(":
                    bCount += 1
                elif token[1] == ")":
                    bCount -= 1

                if bCount:
                    expr[-1][1][1].append(token)

            token = lexer.peekNextToken()  # Revert peek

        # Check if next token implies the current token is array
        elif lastToken[0] == "id" and (token[1] == "["
                                       and token[0] == "symbol"):
            lexer.getNextToken()  # consume token
            expr[-1][0] = "array"
            expr[-1][1] = [copy.copy(expr[-1]),
                           []]  # store function with arguments
            bCount = 1
            while bCount:  # Exit on obtaining all parameters
                token = lexer.getNextToken()
                if token[1] == "[" and token[0] == "symbol":
                    bCount += 1
                elif token[1] == "]" and token[0] == "symbol":
                    bCount -= 1

                if bCount:
                    expr[-1][1][1].append(token)

            token = lexer.peekNextToken()  # Revert peek

    return runExpr(expr)