def p_arithmeticexpr_binop(p): """ arithmeticexpr : arithmeticexpr PLUS arithmeticexpr | arithmeticexpr MINUS arithmeticexpr | arithmeticexpr POINTER arithmeticexpr | arithmeticexpr DIVIDE arithmeticexpr """ if(p[2] == "+"): if(not utils.arithmeticTypeCheck(p[1], p[3])): print("Error at +") sys.exit() p[0] = ASTNode('PLUS', p[1].dtype, p[1].pointerdepth, [p[1], p[3]]) elif(p[2] == "-"): if(not utils.arithmeticTypeCheck(p[1], p[3])): print("Error at -") sys.exit() p[0] = ASTNode('MINUS', p[1].dtype, p[1].pointerdepth, [p[1], p[3]]) elif(p[2] == "*"): if(not utils.arithmeticTypeCheck(p[1], p[3])): print("Error at *") sys.exit() p[0] = ASTNode('MUL', p[1].dtype, p[1].pointerdepth, [p[1], p[3]]) else: if(not utils.arithmeticTypeCheck(p[1], p[3])): print("Error at /") sys.exit() p[0] = ASTNode('DIV', p[1].dtype, p[1].pointerdepth, [p[1], p[3]])
def p_returnstmtforfunc(p): """ returnstmtforfunc : returnstmt """ (funcRet, funcDerive, _) = funcSymDict[currentScope] temp = ASTNode('RETURN',funcRet ,funcDerive, []) if not utils.assignmentTypeCheck(temp, p[1], "return"): sys.exit() p[0] = ASTNode('RETURN', p[1].dtype, p[1].pointerdepth, [p[1]])
def p_assignment_leftvar(p): """ assignment : NAME ASSIGN arithmeticexpr """ global currentScope, varSymDict (dtype, pointerdepth) = utils.giveVarSymOutput(p[1], currentScope, varSymDict) nodeL = ASTNode('VAR', dtype, pointerdepth, [p[1]]) if(not utils.assignmentTypeCheck(nodeL, p[3], "assignment")): print("Type mismatch at assignment") sys.exit() p[0] = ASTNode('ASGN', nodeL.dtype, nodeL.pointerdepth, [nodeL, p[3]])
def p_booleanexpr_term(p): """ booleanexpr : booleanexpr OR booleanexpr | booleanexpr AND booleanexpr | LPAREN booleanexpr RPAREN | NEGATION booleanexpr """ if(p[2] == '||'): p[0] = ASTNode('OR', None, None, [p[1], p[3]]) elif(p[2] == '&&'): p[0] = ASTNode('AND', None, None, [p[1], p[3]]) elif(p[1] == '!'): p[0] = ASTNode('NOT', None, None, [p[2]]) else: p[0] = p[2]
def generate_tree_based_intermediate_code(root: ASTNode, program_container: ProgramContainer): """ Generates a tree-based intermediate code for the program represented by the given AST node. :param root: the root node of the abstract syntax tree that represents the AST node. :param program_container: the container of the program that shall be generated. """ constant_pool = ConstantPool() program_trunk_byte = root.cache(constant_pool) # Concatenates the byte representation of the program. program_byte = bytearray(code_base_header) program_byte.extend(code_version) program_byte.extend(program_container.hash_digest) program_byte.extend(constant_pool.cache()) program_byte.extend(code_program_chapter) program_byte.extend(program_trunk_byte) # Write out the bytecode. if program_container.program_name is None: raise ValueError( 'The program container has too less information for caching the program.' ) with open( join(program_container.program_dir, program_container.program_name + '.lpyc'), 'wb') as out_fd: out_fd.write(program_byte)
def p_functioncall(p): """ functioncall : functioncallname LPAREN functioncalllist RPAREN """ global functionCallParamList, funcSymDict p[0] = ASTNode('CALL', funcSymDict[p[1]][0], funcSymDict[p[1]][1], [p[1], functionCallParamList]) utils.checkTypeParams(functionCallParamList, funcSymDict[p[1]][2], p[1]) functionCallParamList = []
def p_assignment_leftpointer(p): """ assignment : startwithstar ASSIGN arithmeticexpr """ if(not utils.assignmentTypeCheck(p[1], p[3], "assignment")): print("Type mismatch at assignment") sys.exit() p[0] = ASTNode('ASGN', p[1].dtype, p[1].pointerdepth, [p[1], p[3]])
def p_startwithstar_define(p): """ startwithstar : POINTER startwithany """ if(p[2].pointerdepth - 1 < 0): print("Pointer depth less than zero") sys.exit() p[0] = ASTNode('DEREF', p[2].dtype, p[2].pointerdepth - 1, [p[2]])
def p_arithmeticexpr_uminus(p): """ arithmeticexpr : MINUS arithmeticexpr %prec UMINUS """ if(p[2].pointerdepth == 0): if(p[2].data == 'VAR'): print("Direct base type access in UMINUS operation") sys.exit() p[0] = ASTNode('UMINUS', p[2].dtype, p[2].pointerdepth, [p[2]])
def p_startwithany_define(p): """ startwithany : POINTER startwithany | AMPERSAND NAME | NAME """ global varSymDict, currentScope if(p[1] == "*"): if(p[2].pointerdepth - 1 < 0): print("Pointer depth less than zero") sys.exit() p[0] = ASTNode('DEREF', p[2].dtype, p[2].pointerdepth - 1, [p[2]]) elif(p[1] == "&"): (dtype, pointerdepth) = utils.giveVarSymOutput(p[2], currentScope, varSymDict) p[0] = ASTNode('ADDR', dtype, pointerdepth + 1, [ASTNode('VAR', dtype, pointerdepth, [p[2]])]) else: (dtype, pointerdepth) = utils.giveVarSymOutput(p[1], currentScope, varSymDict) p[0] = ASTNode('VAR', dtype, pointerdepth, [p[1]])
def giveCFGFile(fnode, fileName): CFGfileName = fileName + ".cfg" CFGFile = open(CFGfileName, "w") blockCount = -1 temp = 0 for fitem in fnode: z = helperForCFG(fitem.name, fitem.paramList) CFGFile.write(z) x = ASTNode('IF', None, None, [True, fitem.ASTList]) blocks1 = x.giveBlocks() blocks = blocks1[1] for i in range(1, len(blocks)): CFGFile.write("\n<bb " + str(i + blockCount) + ">\n") a = blocks[i] if a[-1] == 'IF': var, temp, lis = a[0].expand(temp, "") CFGFile.write(lis) CFGFile.write("if(" + var + ") goto <bb " + str(blockCount + a[1] - 1) + ">\n") CFGFile.write("else goto <bb " + str(blockCount + a[2] - 1) + ">\n") elif a[-1] == 'GOTO': for j in range(0, len(a) - 2): var, temp, lis = a[j].expand(temp, "") CFGFile.write(lis) CFGFile.write("goto <bb " + str(blockCount + a[len(a) - 2] - 1) + ">\n") else: if (fitem.returnSTMT is not None): if (len(fitem.returnSTMT) > 0): var, temp, lis = fitem.returnSTMT[0].expand(temp, "") CFGFile.write(lis) else: CFGFile.write("return\n\n") else: CFGFile.write("return\n\n") blockCount += len(blocks) - 1
def generate_tree_based_intermediate_code(root: ASTNode, program_container: ProgramContainer): """ Generates a tree-based intermediate code for the program represented by the given AST node. :param root: the root node of the abstract syntax tree that represents the AST node. :param program_container: the container of the program that shall be generated. """ constant_pool = ConstantPool() program_trunk_byte = root.cache(constant_pool) # Concatenates the byte representation of the program. program_byte = bytearray(code_base_header) program_byte.extend(code_version) program_byte.extend(program_container.hash_digest) program_byte.extend(constant_pool.cache()) program_byte.extend(code_program_chapter) program_byte.extend(program_trunk_byte) # Write out the bytecode. if program_container.program_name is None: raise ValueError('The program container has too less information for caching the program.') with open(join(program_container.program_dir, program_container.program_name + '.lpyc'), 'wb') as out_fd: out_fd.write(program_byte)
def p_boolfromarith_def(p): """ boolfromarith : arithmeticexpr LTE arithmeticexpr | arithmeticexpr GTE arithmeticexpr | arithmeticexpr LT arithmeticexpr | arithmeticexpr GT arithmeticexpr | arithmeticexpr COMPARENOTEQUAL arithmeticexpr | arithmeticexpr COMPAREEQUAL arithmeticexpr """ if not utils.assignmentTypeCheck(p[1], p[3], "comparison"): sys.exit() if(p[2] == '<='): p[0] = ASTNode('LE', None, None, [p[1], p[3]]) elif(p[2] == '>='): p[0] = ASTNode('GE', None, None, [p[1], p[3]]) elif(p[2] == '<'): p[0] = ASTNode('LT', None, None, [p[1], p[3]]) elif(p[2] == '>'): p[0] = ASTNode('GT', None, None, [p[1], p[3]]) elif(p[2] == '!='): p[0] = ASTNode('NE', None, None, [p[1], p[3]]) else: p[0] = ASTNode('EQ', None, None, [p[1], p[3]])
def p_arithmeticexpr_terminal_floatnumber(p): """ arithmeticexpr : FLOATNUM """ p[0] = ASTNode('CONST', 'float', 0, [p[1]])
def p_arithmeticexpr_terminal_number(p): """ arithmeticexpr : NUMBER """ p[0] = ASTNode('CONST', 'int', 0, [p[1]])
def writeFS(f, varSymDict, blockCount): li = [] for i in varSymDict.keys(): if i[1] == f.name and varSymDict[i][2] == 0: li.append(i[0]) li.sort() spaceForF = 0 varAccessDict = {} for i in li: if (varSymDict[(i, f.name)][0] == 'int' or varSymDict[(i, f.name)][1] > 0): spaceForF += 4 else: spaceForF += 8 varAccessDict[i] = spaceForF free_reglist = list(range(18)) stri = "" stri += ('\t.text\t# The .text assembler directive indicates\n') stri += ('\t.globl ' + str(f.name) + '\t# The following is the code\n') stri += (str(f.name) + ":\n") stri += ( "# Prologue begins\n\tsw $ra, 0($sp)\t# Save the return address\n\tsw $fp, -4($sp)\t# Save the frame pointer\n\tsub $fp, $sp, 8\t# Update the frame pointer\n\tsub $sp, $sp, " + str(8 + spaceForF) + "\t# Make space for the locals\n# Prologue ends\n") spaceForFcpy = spaceForF + 8 fparams = f.paramList for i in fparams: if (i[0] == 'int' or i[1] > 0): spaceForFcpy += 4 else: spaceForFcpy += 8 varAccessDict[i[2]] = spaceForFcpy newblockCount = blockCount x = ASTNode('IF', None, None, [True, f.ASTList]) blocks1 = x.giveBlocks() blocks = blocks1[1] for i in range(1, len(blocks)): free_reglist = list(range(18)) # this initialisation of free_reglist idk if its true stri += ("label" + str(i + blockCount) + ":\n") a = blocks[i] if a[-1] == 'IF': var, free_reglist, lis = a[0].expand_assembly( free_reglist, "", varAccessDict, False, i + blockCount) stri += lis stri += ("\tbne " + num_to_reg(var) + ", $0, label" + str(blockCount + a[1] - 1) + "\n\tj label" + str(blockCount + a[2] - 1) + "\n") elif a[-1] == 'GOTO': for j in range(0, len(a) - 2): var, free_reglist, lis = a[j].expand_assembly( free_reglist, "", varAccessDict, False, i + blockCount) stri += lis stri += ("\tj label" + str(blockCount + a[len(a) - 2] - 1) + "\n") else: if (f.returnSTMT is not None): if (len(f.returnSTMT) > 0): var, free_reglist, lis = f.returnSTMT[0].expand_assembly( free_reglist, "", varAccessDict, False, i + blockCount) stri += lis stri += ("\tj epilogue_" + (str(f.name)) + "\n") newblockCount += len(blocks) - 1 stri += ( "\n# Epilogue begins\nepilogue_" + str(f.name) + ":\n" + "\tadd $sp, $sp, " + str(8 + spaceForF) + "\n\tlw $fp, -4($sp)\n\tlw $ra, 0($sp)\n\tjr $ra\t# Jump back to the called procedure\n# Epilogue ends\n" ) return stri, newblockCount
def p_whileblock(p): """ whileblock : WHILE LPAREN condition RPAREN conditionalbody """ p[0] = ASTNode('WHILE', None, None, [p[3], p[5]])
def p_ifblock_else(p): """ ifblock : IF LPAREN condition RPAREN conditionalbody ELSE elseconditionalbody """ p[0] = ASTNode('IFELSE', None, None, [p[3], p[5], p[7]])
def p_ifblock_if(p): """ ifblock : IF LPAREN condition RPAREN conditionalbody """ p[0] = ASTNode('IF', None, None, [p[3], p[5]])