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_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_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_value_parameter(p): '''value_parameter : identifiers COLON type_identifier | IDENTIFIER COLON type_identifier | identifiers COLON KEYWORD_ARRAY KEYWORD_OF type_identifier | IDENTIFIER COLON KEYWORD_ARRAY KEYWORD_OF type_identifier''' p[0] = IG.Node() if len(p) == 4: if type(p[1]) == IG.Node: p[0].items = p[1].items for item in p[1].items: ST.currSymTab.addVar(item, p[3].type, isParameter=True) else: p[0].items.append(p[1]) ST.currSymTab.addVar(p[1], p[3].type, isParameter=True) elif len(p) == 5: if type(p[1]) == IG.Node: p[0].items = p[1].items for item in p[1].items: ST.currSymTab.addVar(item, ST.Type('array', ST.Type.ARRAY, arrayBaseType=p[5].type), isParameter=True) else: p[0].items.append(p[1]) ST.currSymTab.addVar(p[1], ST.Type('array', ST.Type.ARRAY, arrayBaseType=p[5].type), isParameter=True)
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_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_parameter_list(p): '''parameter_list : LEFT_PARENTHESIS parameter_declarations RIGHT_PARENTHESIS | LEFT_PARENTHESIS RIGHT_PARENTHESIS''' if len(p) == 4: p[0] = p[2] elif len(p) == 3: p[0] = IG.Node()
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_var_statements(p): '''var_statements : var_statements var_statement | var_statement''' p[0] = IG.Node() if len(p) == 3: p[0].code = p[1].code + p[2].code elif len(p) == 2: p[0].code = p[1].code
def p_boolean_range(p): '''boolean_range : CONSTANT_BOOLEAN_FALSE DOTDOT CONSTANT_BOOLEAN_FALSE | CONSTANT_BOOLEAN_FALSE DOTDOT CONSTANT_BOOLEAN_TRUE | CONSTANT_BOOLEAN_TRUE DOTDOT CONSTANT_BOOLEAN_TRUE''' p[0] = IG.Node() p[0].arrayBeginList = [p[1]] p[0].arrayEndList = [p[3]]
def p_declarations(p): '''declarations : declarations const_declarations | declarations type_declarations | declarations var_declarations | empty''' p[0] = IG.Node() if len(p) == 3: p[0].code = p[1].code + p[2].code
def p_identifiers(p): '''identifiers : identifiers COMMA IDENTIFIER | IDENTIFIER COMMA IDENTIFIER''' p[0] = IG.Node() if type(p[1]) == IG.Node: p[0].items = p[1].items + [p[3]] else: p[0].items = [p[1], p[3]]
def p_array_declaration(p): '''array_declaration : KEYWORD_ARRAY LEFT_SQUARE_BRACKETS array_ranges RIGHT_SQUARE_BRACKETS KEYWORD_OF type''' p[0] = IG.Node() p[0].type = ST.Type('array', ST.Type.ARRAY, arrayBeginList=p[3].arrayBeginList, arrayEndList=p[3].arrayEndList, arrayBaseType=p[6].type)
def p_expression_list(p): '''expression_list : expression_list COMMA expression | expression''' p[0] = IG.Node() if len(p) == 4: p[0].items = p[1].items + [p[3].place] else: p[0].items = [p[1].place]
def p_const_statements(p): '''const_statements : const_statements const_statement | const_statement''' p[0] = IG.Node() if len(p) == 3: p[0].code = p[1].code + p[2].code elif len(p) == 2: p[0].code = p[1].code
def p_parameter_declarations(p): '''parameter_declarations : parameter_declarations SEMICOLON value_parameter | value_parameter''' p[0] = IG.Node() if len(p) == 4: p[0].items = p[1].items + p[3].items p[0].code = p[1].code + p[3].code elif len(p) == 2: p[0] = p[1]
def p_array_index_cstyle(p): '''array_index_cstyle : array_index_cstyle LEFT_SQUARE_BRACKETS expression RIGHT_SQUARE_BRACKETS | LEFT_SQUARE_BRACKETS expression RIGHT_SQUARE_BRACKETS''' p[0] = IG.Node() if len(p) == 4: p[0] = p[2] else: # TODO Handle Multi Dimensional pass
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_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_array_ranges(p): '''array_ranges : array_ranges COMMA array_range | array_range''' p[0] = IG.Node() if len(p) == 4: p[0].arrayBeginList = p[1].arrayBeginList + p[3].arrayBeginList p[0].arrayEndList = p[1].arrayEndList + p[3].arrayEndList else: p[0].arrayBeginList = p[1].arrayBeginList p[0].arrayEndList = p[1].arrayEndList
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_integer_range(p): '''integer_range : CONSTANT_INTEGER DOTDOT CONSTANT_INTEGER''' p[0] = IG.Node() if (p[1] <= p[3]): p[0].arrayBeginList = [p[1]] p[0].arrayEndList = [p[3]] else: print_error("Semantic error at line", p.lineno(3)) print_error("\tEnd index is less than start index") sys.exit(1)
def p_char_range(p): '''char_range : char DOTDOT char''' p[0] = IG.Node() if (p[1] <= p[3]): p[0].arrayBeginList = [p[1]] p[0].arrayEndList = [p[3]] else: print_error("Semantic error at line", p.lineno(3)) print_error("\tEnd index is less than start index") sys.exit(1)
def p_statements(p): '''statements : statements SEMICOLON marker_statement statement | statement''' p[0] = IG.Node() if len(p) == 5: p[0].code = p[1].code + p[3].code p[0].nextList = p[4].nextList backpatch(p[1].nextList, p[3].quad) elif len(p) == 2: p[0] = p[1]
def p_variable_reference(p): '''variable_reference : IDENTIFIER | IDENTIFIER LEFT_SQUARE_BRACKETS array_index RIGHT_SQUARE_BRACKETS | IDENTIFIER array_index_cstyle''' p[0] = IG.Node() STEntry = ST.lookup(p[1]) if STEntry: if len(p) == 2: p[0].place = STEntry p[0].type = STEntry.type elif len(p) == 3: p[0].place = IG.ArrayElement(STEntry, p[2].place)
def p_global_decs_defs(p): '''global_decs_defs : global_decs_defs const_declarations | global_decs_defs type_declarations | global_decs_defs var_declarations | global_decs_defs marker_fpdef func_def | global_decs_defs marker_fpdef proc_def | empty''' p[0] = IG.Node() if len(p) == 3: p[0].code = p[1].code + p[2].code # Assuming type_declarations # is also a node with code elif len(p) == 4: backpatch([p[2].quad], IG.nextQuad) p[0].code = p[1].code + p[2].code + p[3].code else: pass
def p_unsigned_constant(p): '''unsigned_constant : CONSTANT_INTEGER | CONSTANT_HEX | CONSTANT_BINARY | CONSTANT_OCTAL | CONSTANT_NIL | CONSTANT_BOOLEAN_TRUE | CONSTANT_BOOLEAN_FALSE | string''' p[0] = IG.Node() p[0].place = p[1] if type(p[1]) == int: p[0].type = ST.Type('integer', ST.Type.INT) elif type(p[1]) == str: if p[1] == 'true' or p[1] == 'false': p[0].type = ST.Type('boolean', ST.Type.BOOL) else: # TODO Nil is string FIXME p[0].type = ST.Type('string', ST.Type.STRING)
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]