def exitWhile_stmt(self, ctx: LittleParser.While_stmtContext): self.exitScope() while_node = ASTNode(node_enum(14).name, []) end_node = ASTNode(node_enum(16).name, []) end_label = ASTNode(node_enum(10).name, "label" + self.getScopeNum()) # grab nodes from the stack needed to create a WHILE node stmt_list = ast_stack.pop() comp_op = ast_stack.pop() # add the end label to the comp-op node comp_op.val_type = end_label w_label = ast_stack.pop() # END node contains the while label and the endwhile label end_node.value.append(w_label) end_node.value.append(end_label) end_node.val_type = 'while' # WHILE.value = [comp_op, stmt_list, end] while_node.value.append(comp_op) while_node.value.append(stmt_list) while_node.value.append(end_node) while_node.val_type = w_label ast_stack.push(while_node)
def enterFactor_prefix(self, ctx: LittleParser.Factor_prefixContext): # If the expr_prefix has no children(is NULL) add a Null node to the stack if ctx.getChildCount() != 0 and ctx.getChild(0).getChildCount() == 0: node = ASTNode(node_enum(0).name, "") #NullNode ast_stack.push(node) elif ctx.getChildCount() == 0: node = ASTNode(node_enum(6).name, "") #Placeholder node ast_stack.push(node)
def exitElse_part(self, ctx: LittleParser.Else_partContext): self.exitScope() if ast_stack.peek().node_type == node_enum(6).name: pass else: stmtList = ast_stack.pop() label = ast_stack.pop() node = ASTNode(node_enum(15).name, [stmtList], label) ast_stack.push(node)
def enterElse_part(self, ctx: LittleParser.Else_partContext): if ctx.getChildCount() == 0: node = ASTNode(node_enum(6).name, "") #Placeholder node ast_stack.push(node) else: num = self.getScopeNum() name = "BLOCK " + num self.enterScope(name) ast_stack.push(ASTNode(node_enum(10).name, "label" + num))
def enterWrite_stmt(self, ctx: LittleParser.Write_stmtContext): currentScope = self.getCurrentScope() node = ASTNode(node_enum(8).name, [], "") i = 0 while i < ctx.getChild(2).getChildCount(): var = ctx.getChild(2).getChild(i).getText() var = var.split(",") if len(var) > 1: for v in var: if (v != ""): if v in symbolTable[currentScope]: var_type = symbolTable[currentScope][v][0] elif v in symbolTable['GLOBAL']: var_type = symbolTable['GLOBAL'][v][0] node.value.append((v, var_type)) else: if (var[0] != ""): # get the type for node, first check if its in the current scope else get it from global scope if var[0] in symbolTable[currentScope]: var_type = symbolTable[currentScope][var[0]][0] elif var[0] in symbolTable['GLOBAL']: var_type = symbolTable['GLOBAL'][var[0]][0] node.value.append((var[0], var_type)) # statements_node.add("", node) i += 1 ast_stack.push(node)
def exitStmt_list(self, ctx: LittleParser.Stmt_listContext): # If node is a Placeholder if ast_stack.peek().node_type == node_enum(6).name: ast_stack.pop() node = ASTNode(node_enum(5).name, []) ast_stack.push(node) # add a statement to the statement list and push back on to stack else: sl = ast_stack.pop() stmt = ast_stack.pop() sl.value.insert(0, stmt) ast_stack.push(sl)
def exitFactor_prefix(self, ctx: LittleParser.Factor_prefixContext): if ast_stack.peek().node_type == node_enum( 6).name: # if a placeholder node ast_stack.pop() else: mulop_node = ast_stack.pop() postfix_node = ast_stack.pop() fact_prefix_node = ast_stack.pop() if fact_prefix_node.node_type == node_enum(0).name: mulop_node.leftChild = postfix_node else: fact_prefix_node.rightChild = postfix_node mulop_node.leftChild = fact_prefix_node ast_stack.push(mulop_node)
def exitExpr_prefix(self, ctx: LittleParser.Expr_prefixContext): if ast_stack.peek().node_type == node_enum( 6).name: # if a placeholder node ast_stack.pop() else: addop_node = ast_stack.pop() factor_node = ast_stack.pop() prefix_node = ast_stack.pop() if prefix_node.node_type == node_enum(0).name: addop_node.leftChild = factor_node else: prefix_node.rightChild = factor_node addop_node.leftChild = prefix_node ast_stack.push(addop_node)
def exitFactor(self, ctx: LittleParser.FactorContext): postfix_node = ast_stack.pop() factor_prefix_node = ast_stack.pop() if factor_prefix_node.node_type == node_enum(0).name: ast_stack.push(postfix_node) else: factor_prefix_node.rightChild = postfix_node ast_stack.push(factor_prefix_node)
def enterAssign_expr(self, ctx: LittleParser.Assign_exprContext): # print(";Enter Assignment") var1 = ctx.getChild(0).getText() var2 = ctx.getChild(1).getText() var_type = "" currentScope = self.getCurrentScope() # get the type for id_node, first check if its in the current scope else get it from global scope if var1 in symbolTable[currentScope]: var_type = symbolTable[currentScope][var1][0] elif var1 in symbolTable['GLOBAL']: var_type = symbolTable['GLOBAL'][var1][0] # create varref node id_node = ASTNode(node_enum(3).name, var1, var_type) ast_stack.push(id_node) # create assexp node node = ASTNode(node_enum(4).name, var2) ast_stack.push(node)
def exitExpr(self, ctx: LittleParser.ExprContext): factor_node = ast_stack.pop() expr_prefix_node = ast_stack.pop() if expr_prefix_node.node_type == node_enum(0).name: ast_stack.push(factor_node) else: expr_prefix_node.rightChild = factor_node ast_stack.push(expr_prefix_node)
def exitIf_stmt(self, ctx: LittleParser.If_stmtContext): self.exitScope() if_node = ASTNode(node_enum(13).name, [], "") end_node = ASTNode(node_enum(16).name, []) else_node = ast_stack.pop() sl_node = ast_stack.pop() comp_node = ast_stack.pop() if_label = ast_stack.pop() end_label = ASTNode(node_enum(10).name, "label" + self.getScopeNum()) end_node.value.append(if_label) end_node.value.append(end_label) end_node.val_type = 'if' if_node.val_type = if_label if_node.value.append(comp_node) if_node.value.append(sl_node) # if not a placeholder node, # assign the else label to the cop_op node, add the end node to the else values # add else node to the end of if's value list if else_node.node_type != node_enum(6).name: eend_node = ASTNode(node_enum(16).name, [if_label, end_label]) eend_node.val_type = 'else' else_label = else_node.val_type comp_node.val_type = else_label else_node.value.append(end_node) if_node.value.append(eend_node) if_node.value.append(else_node) else: comp_node.val_type = end_label if_node.value.append(end_node) ast_stack.push(if_node)
def postOrder(self, root): if root != None: print("ENTER root") root.pprint() left_obj = self.postOrder(root.leftChild) print("LEFT_OBJ: ") print(left_obj) right_obj = self.postOrder(root.rightChild) print("RIGHT_OBJ: ") print(right_obj) tempLoc = "" tempType = "" current_code = [] # if the root has a type if not, it's a const. and create a temp to store. if root.node_type == node_enum(3).name and root.val_type == "": tempLoc = self.getTemp() #gets a new temp value tempType = "" print("Ready to append IR Node") current_code.append(IRNode("STORE", root.value, "", tempLoc)) elif root.node_type == node_enum(3).name: tempLoc = root.value tempType = root.val_type if root.leftChild: for code in left_obj.getCode(): current_code.append(code) if root.rightChild: for code in right_obj.getCode(): current_code.append(code) return CodeObject(current_code, tempLoc, tempType) #if root has type, check if its node_type is VARREF # IRNode "LOAD" print("ROOT is None, return")
def enterPrimary(self, ctx: LittleParser.PrimaryContext): if ctx.getChildCount() > 1: pass else: var = ctx.getChild(0).getText() var_type = "" currentScope = self.getCurrentScope() # get the type for id_node, first check if its in the current scope else get it from global scope if var in symbolTable[currentScope]: var_type = symbolTable[currentScope][var][0] elif var in symbolTable['GLOBAL']: var_type = symbolTable['GLOBAL'][var][0] node = ASTNode(node_enum(3).name, var, var_type) ast_stack.push(node)
def enterRead_stmt(self, ctx: LittleParser.Read_stmtContext): i = 0 # A read node's values will be a list of tuples [(variable, type), (var, type)] node = ASTNode(node_enum(7).name, [], "") while i < ctx.getChild(2).getChildCount(): var = ctx.getChild(2).getChild(i).getText() var = var.strip(",") var_type = "" currentScope = self.getCurrentScope() # get the type for node, first check if its in the current scope else get it from global scope if var in symbolTable[currentScope]: var_type = symbolTable[currentScope][var][0] elif var in symbolTable['GLOBAL']: var_type = symbolTable['GLOBAL'][var][0] if var != "": node.value.append((var, var_type)) i += 1 ast_stack.push(node)
def postOrder(self, root): if root != None: left_obj = self.postOrder(root.leftChild) right_obj = self.postOrder(root.rightChild) tempLoc = "" tempType = "" current_code = [] # if the root is a VARREF node and it does not have a type, it's a const. # Create a temp, determine the type, store code in IRnode. if root.node_type == node_enum(3).name and root.val_type == "": tempLoc = self.getTemp() #gets a new temp value tempType = "" # determine if the const is an int or a float to get the correct instruction tempType = self.is_number(root.value) # get the correct instruction depending on the type op = self.returnOperator("STORE", tempType) node = IRNode(op, root.value, tempType, tempLoc) tiny_list.append(node.operator_map[op](node)) current_code.append(node) # if the root is a VARREF variable, store its value and type elif root.node_type == node_enum(3).name: tempLoc = root.value tempType = root.val_type # for READ nodes, iterate through value, type tuples elif root.node_type == node_enum(7).name: for tup in root.value: tempLoc = tup[0] tempType = tup[1] #get the correct instruction depending on the type op = self.returnOperator("READ", tempType) node = IRNode(op, tempLoc, "", tempLoc) tiny_list.append(node.operator_map[op](node)) current_code.append(node) # if the root is an assignment statement, store the result from the right child # into the variable of the left child elif root.node_type == node_enum(4).name: tempLoc = root.leftChild.value tempType = left_obj.resType #get the correct instruction depending on the type op = self.returnOperator("STORE", tempType) node = IRNode(op, right_obj.resultLoc, "", tempLoc) tiny_list.append(node.operator_map[op](node)) current_code.append(node) # if the root is an ADDOP, add/subtract the memory locations together # and store in a new temp elif root.node_type == node_enum(1).name: tempLoc = self.getTemp() tempType = left_obj.resType #get the correct instruction depending on the type opType = self.getOpType(root.value) op = self.returnOperator(opType, tempType) node = IRNode(op, left_obj.resultLoc, right_obj.resultLoc, tempLoc) tiny_list.append(node.operator_map[op](node)) current_code.append(node) # if the root is a MULOP, multiply/divide the child memory locations together # and store in a new temp elif root.node_type == node_enum(2).name: tempLoc = self.getTemp() tempType = right_obj.resType #get the correct instruction depending on the type opType = self.getOpType(root.value) op = self.returnOperator(opType, tempType) node = IRNode(op, left_obj.resultLoc, right_obj.resultLoc, tempLoc) tiny_list.append(node.operator_map[op](node)) current_code.append(node) # for WRITE nodes, iterate through value, type tuples elif root.node_type == node_enum(8).name: for tup in root.value: tempLoc = tup[0] tempType = tup[1] op = self.returnOperator("WRITE", tempType) node = IRNode(op, "", "", tempLoc) tiny_list.append(node.operator_map[op](node)) current_code.append(node) elif root.node_type == node_enum(10).name: node = IRNode("LABEL", '', '', root.value) tiny_list.append(node.operator_map["LABEL"](node)) current_code.append(node) # iterate through statement list node - not sure what functionality to add here elif root.node_type == node_enum(5).name: for value in root.value: self.postOrder(value) # if the node is a WHILE node elif root.node_type == node_enum(14).name: comp = root.value[0].value tiny_code = 'label ' + root.val_type.value tiny_list.append(tiny_code) #recurse on the nodes in the value list for value in root.value: self.postOrder(value) #if the node is a COMPOP, find its value and create an IR node elif root.node_type == node_enum(9).name: tempType = left_obj.resType opType = self.getOpType(root.value) op = self.returnOperator(opType, tempType) result = root.val_type.value node = IRNode(op, left_obj.resultLoc, right_obj.resultLoc, result) tiny_list.append(node.operator_map[op](node)) current_code.append(node) #if the node if an IF node elif root.node_type == node_enum(13).name: # tiny_code = 'label ' + root.val_type.value # tiny_list.append(tiny_code) #recurse on the nodes in the value list for value in root.value: self.postOrder(value) #if the node is an ELSE node elif root.node_type == node_enum(15).name: # jump = root.value[1].value[1].value tiny_code = 'label %s' % (root.val_type.value) tiny_list.append(tiny_code) #recurse on the nodes in the value list for value in root.value: self.postOrder(value) #if the node is an END node elif root.node_type == node_enum(16).name: nodes = root.value if root.val_type == 'while': jump = nodes[0].value label = nodes[1].value tiny_code = 'jmp %s\nlabel %s' % (jump, label) tiny_list.append(tiny_code) elif root.val_type == 'if': label = nodes[1].value tiny_code = 'label %s' % (label) if self.dupCode(tiny_code, tiny_list): pass else: tiny_list.append(tiny_code) elif root.val_type == 'else': # print("in else end") label = nodes[1].value # print(label) tiny_code = 'jmp %s' % (label) tiny_list.append(tiny_code) # adding the code objects to the new list I created co = CodeObject(current_code, tempLoc, tempType) if co is not None: code_objects.append(co) return co
def enterFunc_decl(self, ctx: LittleParser.Func_declContext): name = ctx.getChild(2).getText() self.enterScope(name) ast_stack.push(ASTNode(node_enum(10).name, name))
def enterStmt_list(self, ctx: LittleParser.Stmt_listContext): if ctx.getChildCount() == 0: node = ASTNode(node_enum(6).name, []) ast_stack.push(node)
def enterCompop(self, ctx: LittleParser.CompopContext): # The label to jump to will be added in the exit while and exit if functions as the val_type node = ASTNode(node_enum(9).name, ctx.getText()) ast_stack.push(node)
def enterMulop(self, ctx: LittleParser.MulopContext): node = ASTNode(node_enum(2).name, ctx.getChild(0).getText()) ast_stack.push(node)
def enterWhile_stmt(self, ctx: LittleParser.While_stmtContext): num = self.getScopeNum() name = "BLOCK " + num self.enterScope(name) ast_stack.push(ASTNode(node_enum(10).name, "label" + num))
def postOrder(self, root): if root != None: left_obj = self.postOrder(root.leftChild) right_obj = self.postOrder(root.rightChild) tempLoc = "" tempType = "" current_code = [] # if the root is a VARREF node and it does not have a type, it's a const. # Create a temp, determine the type, store code in IRnode. if root.node_type == node_enum(3).name and root.val_type == "": tempLoc = self.getTemp() #gets a new temp value tempType = "" # determine if the const is an int or a float to get the correct instruction tempType = self.is_number(root.value) # get the correct instruction depending on the type op = self.returnOperator("STORE", tempType) node = IRNode(op, root.value, tempType, tempLoc) tiny_list.append(node.operator_map[op](node)) current_code.append(node) # if the root is a VARREF variable, store its value and type # do we not create an ir node yet?? elif root.node_type == node_enum(3).name: tempLoc = root.value tempType = root.val_type # **** Is there a reason we aren't storing the type here? # for READ nodes, iterate through value, type tuples elif root.node_type == node_enum(7).name: for value in root.value: tempLoc = root.value[0] tempType = root.value[1] #get the correct instruction depending on the type op = self.returnOperator("READ", tempType) node = IRNode(op, tempLoc, "", tempLoc) tiny_list.append(node.operator_map[op](node)) current_code.append(node) # if the root is an assignment statement, store the result from the right child # into the variable of the left child elif root.node_type == node_enum(4).name: tempLoc = root.leftChild.value tempType = left_obj.resType #get the correct instruction depending on the type op = self.returnOperator("STORE", tempType) node = IRNode(op, right_obj.resultLoc, "", tempLoc) tiny_list.append(node.operator_map[op](node)) current_code.append(node) # if the root is an ADDOP, add/subtract the memory locations together # and store in a new temp elif root.node_type == node_enum(1).name: tempLoc = self.getTemp() tempType = left_obj.resType #get the correct instruction depending on the type opType = self.getOpType(root.value) op = self.returnOperator(opType, tempType) node = IRNode(op, left_obj.resultLoc, right_obj.resultLoc, tempLoc) tiny_list.append(node.operator_map[op](node)) current_code.append(node) # if the root is a MULOP, multiply/divide the child memory locations together # and store in a new temp elif root.node_type == node_enum(2).name: tempLoc = self.getTemp() tempType = right_obj.resType #get the correct instruction depending on the type opType = self.getOpType(root.value) op = self.returnOperator(opType, tempType) node = IRNode(op, left_obj.resultLoc, right_obj.resultLoc, tempLoc) tiny_list.append(node.operator_map[op](node)) current_code.append(node) # for WRITE nodes, iterate through value, type tuples elif root.node_type == node_enum(8).name: for value in root.value: tempLoc = root.value[0] tempType = root.val_type[1] op = self.returnOperator("WRITE", tempType) node = IRNode(op, "", "", tempLoc) tiny_list.append(node.operator_map[op](node)) current_code.append(node) elif root.node_type == node_enum(10).name: node = IRNode("LABEL", '', '', root.value) tiny_list.append(node.operator_map["LABEL"](node)) current_code.append(node) # print("Write node contents: " + root.val_type + " " + root.value) # iterate through statement list node - not sure what functionality to add here elif root.node_type == node_enum(5).name: for value in root.value: self.postOrder(value) # if the node is a while node elif root.node_type == node_enum(14).name: #use the while label to find the destination label tempLoc = jumpLabel(root.val_type.value) #get the comparison operator comp = value[0].value #not super sure if I need to do this #if so, recurse on the nodes in the value list for value in root.value: self.postOrder(value) #for the IRNodes that are in the current_code list, find the node for the comparison operator for code in current_code: # if you find the correct node, remove the node so it can be modified if comp == code.operation: node = current_code.remove(code) #set the node's destination location with the label node.result = tempLoc current_code.append(node) tiny_list.append(node.operator_map["JUMP"](node)) elif root.node_type == node_enum(9).name: tempType = left_obj.resType opType = self.getOpType(root.value) node = IRNode(op, left_obj.resultLoc, right_obj.resultLoc, "") current_code.append(node) # I commented this out because it ended up storing the instructions in the incorrect order # if root.leftChild: # for code in left_obj.getCode(): # current_code.append(code) # if root.rightChild: # for code in right_obj.getCode(): # current_code.append(code) # adding the code objects to the new list I created co = CodeObject(current_code, tempLoc, tempType) if co is not None: code_objects.append(co) return co
def enterExpr(self, ctx: LittleParser.ExprContext): if ctx.getChild(0).getChildCount() == 0: ast_stack.push(ASTNode(node_enum(0).name, "")) #push