예제 #1
0
def p_expressions_function_call(p):
    """expressions      : ID LPAR arguments_list RPAR"""
    procedure = p[1]
    symbol_table.check_procedure_declaration(procedure, p.slice[1])
    if len(p[3]) != len(procedure["parameters"]):
        raise CompilationException(
            "function call didn't match with function \'" +
            procedure["place"] + "\' declaration!", p.slice[1])
    code_array.save_context()
    code_array.emit(
        "store_top",
        symbol_table.get_current_scope_symbol_table().top_stack_variable, None,
        None)
    code_array.emit("push", None, {"value": 0, "type": "int"}, None)
    return_address_variable = symbol_table.get_new_temp_variable("void*")
    code_array.emit("&&", return_address_variable, None, None)
    temp_index = code_array.get_current_quad_index()
    code_array.emit("push", None, return_address_variable, None)
    for argument in p[3]:
        code_array.emit("push", None, argument, None)
    code_array.emit("call", None, procedure["quad_index"], None)
    p[0] = symbol_table.get_new_temp_variable("int")
    code_array.emit("pop", p[0], None, None)
    code_array.backpatch_e_list([temp_index],
                                code_array.get_current_quad_index())
    code_array.restore_context()
    return
예제 #2
0
def p_arithmetic_expressions(p):
    """arithmetic_expressions       : PLUS pair 
                                    | MINUS pair 
                                    | MULT pair 
                                    | DIV pair 
                                    | MOD pair
                                    | MINUS expressions"""
    if p.slice[2].type == "expressions":
        exp_type = get_type_of_arithmetic_expression(p[1], "int", p[2]["type"],
                                                     p.slice[1])
        p[2] = code_array.store_boolean_expression_in_variable(p[2])
        first_arg = {"value": 0, "type": "int"}
        second_arg = p[2]
    else:
        p[2]["first_arg"] = code_array.store_boolean_expression_in_variable(
            p[2]["first_arg"])
        p[2]["second_arg"] = code_array.store_boolean_expression_in_variable(
            p[2]["second_arg"])
        first_arg = p[2]["first_arg"]
        second_arg = p[2]["second_arg"]
        # pattern = r'(\*|\+|\-|\/)'
        # if re.match(pattern, p[1]):
        exp_type = get_type_of_pair_for_arithmetic_expression(
            p[1], p[2], p.slice[1])
    p[0] = symbol_table.get_new_temp_variable(exp_type)
    code_array.emit(p[1], p[0], first_arg, second_arg)
    if (p[1] == "%" or p[1]
            == "/") and "value" in second_arg and second_arg["value"] == 0:
        raise CompilationException("division by zero!!", p.slice[2])
    return
예제 #3
0
def p_procedure(p):
    """procedure        : PROCEDURE function_sign LBRACE qis_1 declarations_list block RBRACE SEMICOLON
                        | PROCEDURE function_sign LBRACE qis_1 block RBRACE SEMICOLON"""
    if p[len(p) - 3] and "exit_when_quad_index" in p[len(p) - 3]:
        raise CompilationException(
            "exit when just allowed in loops!!! function: " + p[2]["place"],
            p.slice[2])
    procedure = p[2]
    p[0] = procedure

    # goto return statements
    exit_procedure_statements_quad_index = code_array.get_next_quad_index()
    return_address_variable = symbol_table.get_new_temp_variable("void*")
    code_array.emit("pop", return_address_variable, None, None)
    code_array.emit("short jump", None, return_address_variable, None)
    begin_procedure_statements_quad_index = code_array.get_next_quad_index()

    # backpatch qis_1 with begin proc statements
    qis_1 = p[4]
    code_array.backpatch_e_list(qis_1["goto_quad_index"],
                                begin_procedure_statements_quad_index)
    # load arguments
    for parameter in procedure["parameters"]:
        code_array.emit("pop", parameter, None, None)
    # goto beginning of proc
    code_array.emit("goto", None, qis_1["quad_index"], None)
    symbol_table.pop_scope()
    return
예제 #4
0
def p_statement_function_return(p):
    """statement            : RETURN expressions"""
    if p[2]["type"] != "int":
        raise CompilationException(
            "return value can only be in int type!! seen type: " +
            p[2]["type"], p.slice[2])
    # goto return statements
    return_address_variable = symbol_table.get_new_temp_variable("void*")
    code_array.emit("pop", return_address_variable, None, None)
    code_array.emit("pop", symbol_table.get_new_temp_variable("int"), None,
                    None)
    code_array.emit("push", None, p[2], None)
    code_array.emit("short jump", None, return_address_variable, None)
    return
예제 #5
0
def p_fucntion_sign(p):
    """function_sign      : psc ID parameters"""
    sign = {
        "place": p[2]["place"],
        "quad_index": p[1]["quad_index"],
        "parameters": p[3]
    }
    p[0] = sign
    place = sign["place"]
    if place not in symbol_table:
        symbol_table.install_procedure(sign)
    else:
        raise CompilationException(
            "multiple procedure \'" + place + "\' declaration!!", p.slice[2])
    p[0] = sign
    return
예제 #6
0
def p_program(p):
    """program      : PROGRAM psc ID declarations_list qis_1 procedure_list MAIN block
                    | PROGRAM psc ID qis_1 procedure_list MAIN block
                    | PROGRAM psc ID declarations_list MAIN block
                    | PROGRAM psc ID MAIN block"""
    if p[len(p) - 1] and "exit_when_quad_index" in p[len(p) - 1]:
        raise CompilationException(
            "exit when just allowed in loops!!! function: main", p.slice[1])
    symbol_table.set_root()
    if len(p) > 7:
        if len(p) == 9:
            main_goto_quad_index = p[5]
            main_quad_index = p[8]
        else:
            main_goto_quad_index = p[4]
            main_quad_index = p[7]
        code_array.backpatch_e_list(main_goto_quad_index["goto_quad_index"],
                                    main_quad_index["starting_quad_index"])
    return
예제 #7
0
def p_declarations(p):
    """declarations     : type_specifiers declarator_list SEMICOLON"""
    declarations = []
    for declarator in p[2]["declarations_info"]:
        declarator["type"] = p[1]["type"]
        place = declarator["place"]
        if not symbol_table.current_scope_has_variable(place):
            if place in symbol_table:
                should_be_declared = False
            else:
                should_be_declared = True
            index = symbol_table.install_variable(declarator)
            code_array.initialize_variable(declarator)
            symbol_table[index]["should_be_declared"] = should_be_declared
        else:
            raise CompilationException(
                "multiple variable \'" + place + "\' declaration!!",
                p.slice[1])
        declarations.append(declarator)
    p[0] = declarations
    return
예제 #8
0
def t_error(t):
    raise CompilationException("Illegal character " + str(t.value[0]), t)
예제 #9
0
def p_error(p):
    msg = "Syntax error in input!\n" + str(p)
    raise CompilationException(msg, p)
예제 #10
0
def get_type_of_arithmetic_expression(operator, first_arg_type,
                                      second_arg_type, parameter):
    if operator == "%":
        if second_arg_type in ("float", "char"):
            raise CompilationException(
                "operator: %, invalid second parameter type!!!\t seen type: " +
                second_arg_type, parameter)
        if first_arg_type == "int":
            pair_type = "int"
        if first_arg_type == "char":
            if second_arg_type == "int":
                pair_type = "int"
            elif second_arg_type == "bool":
                pair_type = "int"
        if first_arg_type == "float":
            pair_type = "float"
        if first_arg_type == "bool":
            pair_type = "int"
    elif operator == "/":
        if second_arg_type == "char":
            raise CompilationException(
                "operator: /, invalid second parameter type!!!\t seen type: " +
                second_arg_type, parameter)
        if first_arg_type == "int":
            if second_arg_type == "int":
                pair_type = "int"
            elif second_arg_type == "char":
                pair_type = "int"
            elif second_arg_type == "float":
                pair_type = "float"
            elif second_arg_type == "bool":
                pair_type = "int"
        if first_arg_type == "char":
            if second_arg_type == "int":
                pair_type = "int"
            elif second_arg_type == "char":
                pair_type = "int"
            elif second_arg_type == "float":
                pair_type = "float"
            elif second_arg_type == "bool":
                pair_type = "int"
        if first_arg_type == "float":
            pair_type = "float"
        if first_arg_type == "bool":
            if second_arg_type == "int":
                pair_type = "int"
            elif second_arg_type == "char":
                pair_type = "int"
            elif second_arg_type == "float":
                pair_type = "float"
            elif second_arg_type == "bool":
                pair_type = "int"
    elif operator in ("+", "-", "*"):
        if first_arg_type == "int":
            if second_arg_type == "int":
                pair_type = "int"
            elif second_arg_type == "char":
                pair_type = "char"
            elif second_arg_type == "float":
                pair_type = "float"
            elif second_arg_type == "bool":
                pair_type = "int"
        if first_arg_type == "char":
            if second_arg_type == "int":
                pair_type = "char"
            elif second_arg_type == "char":
                pair_type = "char"
            elif second_arg_type == "float":
                pair_type = "float"
            elif second_arg_type == "bool":
                pair_type = "char"
        if first_arg_type == "float":
            pair_type = "float"
        if first_arg_type == "bool":
            if second_arg_type == "int":
                pair_type = "int"
            elif second_arg_type == "char":
                pair_type = "char"
            elif second_arg_type == "float":
                pair_type = "float"
            elif second_arg_type == "bool":
                pair_type = "int"
    return pair_type