def p_function_call(p): '''function_call : IDENTIFIER LEFT_PARENTHESIS expression_list RIGHT_PARENTHESIS | IDENTIFIER LEFT_PARENTHESIS RIGHT_PARENTHESIS''' p[0] = IG.Node() if len(p) == 4: p[0].place = IG.newTempInt() p[0].type = p[0].place.type p[0].genCode( IG.TACInstr(IG.TACInstr.ASSIGN, op=IG.TACInstr.CALLOP, dest=p[0].place, targetLabel=p[1], lineNo=IG.nextQuad)) IG.nextQuad += 1 elif len(p) == 5: p[0].place = IG.newTempInt() p[0].type = p[0].place.type p[0].genCode( IG.TACInstr(IG.TACInstr.ASSIGN, op=IG.TACInstr.CALLOP, dest=p[0].place, lineNo=IG.nextQuad, paramList=p[3].items, targetLabel=p[1])) IG.nextQuad += 1
def p_expression(p): '''expression : simple_expression relational_operator simple_expression | simple_expression''' p[0] = IG.Node() if len(p) == 2: p[0] = p[1] elif len(p) == 4: p[0].code = p[1].code + p[3].code # p[0].place = IG.newTempBool() # p[0].type = p[0].place.type # p[0].genCode(IG.TACInstr(IG.TACInstr.ASSIGN, op=IG.TACInstr.OpMap[p[2]], src1=p[1].place, # src2=p[3].place, dest=p[0].place, lineNo=IG.nextQuad)) p[0].trueList = [IG.nextQuad] p[0].falseList = [IG.nextQuad + 1] print 'Given src2', p[3].place print "Truelist", p[0].trueList print "Falselist", p[0].falseList p[0].genCode( IG.TACInstr(IG.TACInstr.IFGOTO, op=IG.TACInstr.OpMap[p[2]], src1=p[1].place, src2=p[3].place, lineNo=IG.nextQuad)) IG.nextQuad += 1 p[0].genCode(IG.TACInstr(IG.TACInstr.GOTO, lineNo=IG.nextQuad)) IG.nextQuad += 1
def p_factor(p): '''factor : LEFT_PARENTHESIS expression RIGHT_PARENTHESIS | sign factor | OP_NOT factor | OP_BIT_NOT factor | function_call | variable_reference | unsigned_constant''' p[0] = IG.Node() if len(p) == 3: # TODO Generate Code if p[1] == 'not': p[0].trueList = p[2].falseList p[0].falseList = p[2].trueList p[0].code = p[2].code # p[0].genCode(IG.TACInstr(IG.TACInstr.ASSIGN, op=IG.TACInstr.LOGICNOT, src1=p[2].place, # dest=p[0].place, lineNo=IG.nextQuad)) # IG.nextQuad += 1 else: p[0].place = IG.newTempInt() p[0].type = p[0].place.type p[0].code = p[2].code p[0].genCode( IG.TACInstr(IG.TACInstr.ASSIGN, op=IG.TACInstr.OpMap[p[1]], src1=p[1].place, dest=p[0].place, lineNo=IG.nextQuad)) IG.nextQuad += 1 # TODO generate code for other types elif len(p) == 2: p[0] = p[1] if p[1].place == 'true': p[0].trueList = [IG.nextQuad] p[0].genCode(IG.TACInstr(IG.TACInstr.GOTO, lineNo=IG.nextQuad)) IG.nextQuad += 1 elif p[1].place == 'false': p[0].falseList = [IG.nextQuad] p[0].genCode(IG.TACInstr(IG.TACInstr.GOTO, lineNo=IG.nextQuad)) IG.nextQuad += 1 elif type(p[1].place) == ST.SymTabEntry and p[1].place.isBool(): p[0].trueList = [IG.nextQuad] p[0].genCode(IG.TACInstr(IG.TACInstr.GOTO, lineNo=IG.nextQuad)) IG.nextQuad += 1 p[0].falseList = [IG.nextQuad] p[0].genCode(IG.TACInstr(IG.TACInstr.GOTO, lineNo=IG.nextQuad)) IG.nextQuad += 1 elif len(p) == 4: p[0].place = p[2].place p[0].type = p[2].type p[0].trueList = p[2].trueList p[0].falseList = p[2].falseList
def p_marker_fpdef(p): '''marker_fpdef : ''' p[0] = IG.Node() p[0].quad = IG.nextQuad p[0].genCode(IG.TACInstr(IG.TACInstr.GOTO, lineNo=IG.nextQuad)) IG.nextQuad += 1 ST.currSymTab = ST.SymTab(ST.currSymTab)
def p_matched_statement(p): '''matched_statement : simple_statement | structured_statement | KEYWORD_IF expression KEYWORD_THEN marker_if matched_statement \ marker_if_end KEYWORD_ELSE marker_else matched_statement | loop_header matched_statement | KEYWORD_BREAK | KEYWORD_CONTINUE | empty''' p[0] = IG.Node() if len(p) == 2: if type(p[1]) == IG.Node: p[0] = p[1] else: pass # TODO: Handle empty production # TODO: Generate code for break and continue elif len(p) == 10: p[0].code = p[2].code + p[4].code + p[5].code + p[6].code + p[9].code print 'test', p[8].quad backpatch(p[2].falseList, p[8].quad) backpatch(p[2].trueList, p[4].quad) p[0].nextList = p[5].nextList + p[6].nextList + p[9].nextList elif len(p) == 3: p[0].code = p[1].code + p[2].code p[0].genCode( IG.TACInstr(IG.TACInstr.GOTO, target=p[1].quad, lineNo=IG.nextQuad)) IG.nextQuad += 1 backpatch(p[1].endList, IG.nextQuad)
def p_func_head(p): '''func_head : KEYWORD_FUNCTION IDENTIFIER parameter_list COLON type_identifier''' ST.currSymTab.previousTable.addFunction(p[2], p[5].type, len(p[3].items)) STEntry = ST.currSymTab.addVar(p[2], p[5].type) # TODO Type identifier must be builtin/already defined # Generate code TypeSTEntry = ST.lookup(p[5].type.name) if TypeSTEntry is not None: if TypeSTEntry.isType(): p[0] = IG.Node() p[0].place = STEntry p[0].genCode( IG.TACInstr(IG.TACInstr.LABEL, label=p[2], paramList=p[3].items, lineNo=IG.nextQuad)) IG.nextQuad += 1 else: # Variable given as type print_error("Type error at line", p.linespan(5)[1]) print_error("\tVariable identifer given as return type") sys.exit(1) else: # Undefined type print_error("Type error at line", p.linespan(5)[1]) print_error("\tReturn type is not a built in or predefined type") sys.exit(1)
def p_proc_def(p): '''proc_def : proc_head SEMICOLON declarations block SEMICOLON''' ST.currSymTab.previousTable.addTable(ST.currSymTab) ST.currSymTab = ST.currSymTab.previousTable p[0] = IG.Node() p[0].code = p[1].code + p[3].code + p[4].code p[0].genCode(IG.TACInstr(IG.TACInstr.RETURN, lineNo=IG.nextQuad)) IG.nextQuad += 1
def p_const_statement(p): 'const_statement : IDENTIFIER EQUAL expression SEMICOLON' STEntry = ST.currSymTab.addVar(p[1], p[3].type, isConst=True) p[0] = IG.Node() p[0].genCode( IG.TACInstr(IG.TACInstr.ASSIGN, dest=STEntry, src1=p[3].place, lineNo=IG.nextQuad)) IG.nextQuad += 1
def p_assignment_statement(p): '''assignment_statement : variable_reference COLON_EQUAL expression''' p[0] = IG.Node() p[0].nextList = p[3].nextList p[0].genCode( IG.TACInstr(IG.TACInstr.ASSIGN, src1=p[3].place, dest=p[1].place, lineNo=IG.nextQuad)) IG.nextQuad += 1
def p_proc_head(p): 'proc_head : KEYWORD_PROCEDURE IDENTIFIER parameter_list' ST.currSymTab.previousTable.addProcedure(p[2], len(p[3].items)) p[0] = IG.Node() p[0].genCode( IG.TACInstr(IG.TACInstr.LABEL, label=p[2], paramList=p[3].items, lineNo=IG.nextQuad)) IG.nextQuad += 1
def p_marker_while(p): '''marker_while : ''' p[0] = IG.Node() p[0].genCode( IG.TACInstr(IG.TACInstr.IFGOTO, src1=p[-1].place, src2=False, op=IG.TACInstr.EQ, lineNo=IG.nextQuad)) p[0].quad = IG.nextQuad IG.nextQuad += 1
def p_var_statement(p): '''var_statement : identifiers COLON type SEMICOLON | IDENTIFIER COLON type SEMICOLON | IDENTIFIER COLON type EQUAL expression SEMICOLON''' p[0] = IG.Node() if len(p) == 5: if type(p[1]) == IG.Node: for item in p[1].items: STEntry = ST.currSymTab.addVar(item, p[3].type) if STEntry.isArray(): p[0].genCode( IG.TACInstr(IG.TACInstr.DECLARE, dest='array', src1=p[3].type.arrayBeginList[0], src2=p[3].type.arrayEndList[0], lineNo=IG.nextQuad)) IG.nextQuad += 1 else: STEntry = ST.currSymTab.addVar(p[1], p[3].type) if STEntry.isArray(): p[0].genCode( IG.TACInstr(IG.TACInstr.DECLARE, dest='array', src1=p[3].type.arrayBeginList[0], src2=p[3].type.arrayEndList[0], lineNo=IG.nextQuad)) IG.nextQuad += 1 else: STEntry = ST.currSymTab.addVar(p[1], p[3].type) p[0].genCode( IG.TACInstr(IG.TACInstr.ASSIGN, dest=STEntry, src1=p[5].place, lineNo=IG.nextQuad)) IG.nextQuad += 1
def p_term(p): '''term : term OP_MULT factor | term OP_DIV factor | term OP_MOD factor | term OP_AND bool_exp_marker factor | term OP_BIT_AND factor | term OP_SHIFTLEFT factor | term OP_SHIFTRIGHT factor | factor''' p[0] = IG.Node() if len(p) == 5: backpatch(p[1].trueList, p[3].quad) p[0].trueList = p[4].trueList p[0].falseList = p[1].falseList + p[4].falseList p[0].place = IG.newTempBool() p[0].type = p[0].place.type p[0].code = p[1].code + p[4].code # p[0].genCode(IG.TACInstr(IG.TACInstr.ASSIGN, op=IG.TACInstr.LOGICAND, src1=p[1].place, src2=p[4].place, # dest=p[0].place, lineNo=IG.nextQuad)) # IG.nextQuad += 1 elif len(p) == 4: if p[1].type == p[3].type: p[0].place = IG.newTempInt() p[0].type = p[0].place.type p[0].code = p[1].code + p[3].code p[0].genCode( IG.TACInstr(IG.TACInstr.ASSIGN, op=IG.TACInstr.OpMap[p[2]], src1=p[1].place, src2=p[3].place, dest=p[0].place, lineNo=IG.nextQuad)) IG.nextQuad += 1 # TODO Generate code for other types else: # TODO Type checking error pass elif len(p) == 2: p[0] = p[1]
def p_simple_expression(p): '''simple_expression : simple_expression OP_PLUS term | simple_expression OP_MINUS term | simple_expression OP_OR bool_exp_marker term | simple_expression OP_XOR term | simple_expression OP_BIT_OR term | simple_expression OP_BIT_XOR term | term''' p[0] = IG.Node() if len(p) == 5: backpatch(p[1].falseList, p[3].quad) p[0].trueList = p[1].trueList + p[4].trueList p[0].falseList = p[4].falseList p[0].code = p[1].code + p[4].code # p[0].genCode(IG.TACInstr(IG.TACInstr.ASSIGN, op=IG.TACInstr.LOGICOR, src1=p[1].place, src2=p[4].place, # dest=p[0].place, lineNo=IG.nextQuad)) # IG.nextQuad += 1 elif len(p) == 4: if p[1].type == p[3].type: p[0].place = IG.newTempInt() p[0].type = p[0].place.type p[0].code = p[1].code + p[3].code p[0].genCode( IG.TACInstr(IG.TACInstr.ASSIGN, op=IG.TACInstr.OpMap[p[2]], src1=p[1].place, src2=p[3].place, dest=p[0].place, lineNo=IG.nextQuad)) IG.nextQuad += 1 # TODO Generate Code for other types else: # TODO Type checking error pass elif len(p) == 2: p[0] = p[1]
def p_unmatched_statement(p): '''unmatched_statement : KEYWORD_IF expression KEYWORD_THEN marker_if statement | KEYWORD_IF expression KEYWORD_THEN marker_if matched_statement \ marker_if_end KEYWORD_ELSE marker_else unmatched_statement | loop_header unmatched_statement''' p[0] = IG.Node() if len(p) == 6: p[0].code = p[2].code + p[4].code + p[5].code backpatch(p[2].trueList, p[4].quad) p[0].nextList = p[2].falseList + p[5].nextList elif len(p) == 10: p[0].code = p[2].code + p[4].code + p[5].code + p[6].code + p[9].code backpatch(p[2].falseList, p[8].quad) backpatch(p[2].trueList, p[4].quad) p[0].nextList = p[5].nextList + p[6].nextList + p[9].nextList elif len(p) == 3: p[0].code = p[1].code + p[2].code p[0].genCode( IG.TACInstr(IG.TACInstr.GOTO, target=p[1].quad, lineNo=IG.nextQuad)) IG.nextQuad += 1 backpatch(p[1].endList, IG.nextQuad)
def p_start(p): 'start : program_statement global_decs_defs block DOT' p[0] = IG.Node() p[0].code = p[2].code + p[3].code p[0].genCode(IG.TACInstr(IG.TACInstr.RETURN, lineNo=IG.nextQuad)) IG.nextQuad += 1
def p_marker_if_end(p): '''marker_if_end : ''' p[0] = IG.Node() p[0].nextList = [IG.nextQuad] p[0].genCode(IG.TACInstr(IG.TACInstr.GOTO, lineNo=IG.nextQuad)) IG.nextQuad += 1
def p_func_proc_statement(p): '''func_proc_statement : IDENTIFIER LEFT_PARENTHESIS expression_list RIGHT_PARENTHESIS | IDENTIFIER LEFT_PARENTHESIS RIGHT_PARENTHESIS''' p[0] = IG.Node() if len(p) == 5: if p[1] == 'read' or p[1] == 'readln': if len(p[3].items) == 1: # TODO Type Readln FIXME if p[3].items[0].getDeepestType() == ST.Type.INT: ioFmtString = '"%d"' elif p[3].items[0].getDeepestType() == ST.Type.STRING: ioFmtString = '"%s"' elif p[3].items[0].getDeepestType() == ST.Type.CHAR: ioFmtString = '"%c"' else: # TODO ERROR pass # print_error('Type Not Supported for Read Operation') ioArgList = [IG.Operand(item) for item in p[3].items] p[0].genCode( IG.TACInstr(IG.TACInstr.SCANF, ioArgList=ioArgList, ioFmtString=ioFmtString, lineNo=IG.nextQuad)) IG.nextQuad += 1 elif p[1] == 'write' or p[1] == 'writeln': if len(p[3].items) == 1: # TODO Type Writeln FIXME if type(p[3].items[0]) == ST.SymTabEntry or type( p[3].items[0]) == IG.ArrayElement: #print p[3].items[0].type.name, p[3].items[0].type.getDeepestType() if p[3].items[0].type.getDeepestType() == 'integer': ioFmtString = '%d' elif p[3].items[0].type.getDeepestType() == 'string': ioFmtString = '%s' elif p[3].items[0].type.getDeepestType() == 'char': ioFmtString = '%c' else: # TODO ERROR pass # print_error('Type Not Supported for Read Operation') else: if type(p[3].items[0]) == int: ioFmtString = '%d' elif type(p[3].items[0]) == str and len( p[3].items[0]) == 1: ioFmtString = '%c' elif type(p[3].items[0]) == str: ioFmtString = '%s' # TODO Error pass if p[1] == 'writeln': ioFmtString += '\\n' ioFmtString = '"' + ioFmtString + '"' ioArgList = [IG.Operand(item) for item in p[3].items] p[0].genCode( IG.TACInstr(IG.TACInstr.PRINTF, ioArgList=ioArgList, ioFmtString=ioFmtString, lineNo=IG.nextQuad)) IG.nextQuad += 1 else: STEntry = ST.lookup(p[1]) if STEntry and (STEntry.isFunction() or STEntry.isProcedure()): p[0].genCode( IG.TACInstr(IG.TACInstr.CALL, paramList=p[3].items, lineNo=IG.nextQuad, targetLabel=p[1])) IG.nextQuad += 1 else: STEntry = ST.lookup(p[1]) if STEntry and (STEntry.isFunction() or STEntry.isProcedure()): p[0].genCode( IG.TACInstr(IG.TACInstr.CALL, paramList=[], lineNo=IG.nextQuad, targetLabel=p[1])) IG.nextQuad += 1 else: # TODO Type Checking Error pass