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]
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]
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))
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()
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]
def Else(token): peekToken = lexer.peekNextToken() if peekToken[1] != "{" and peekToken[0] != "symbol": Error(token, "Expected '{'") return [1]
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]
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]
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)