예제 #1
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
예제 #2
0
def p_qis_1(p):
    """qis_1      : """
    code_array.emit("goto", None, None, None)
    p[0] = {
        "quad_index": code_array.get_next_quad_index(),
        "goto_quad_index": [code_array.get_current_quad_index()]
    }
    return
예제 #3
0
def p_default(p):
    """default      : DEFAULT COLON qis block"""
    break_quad_index = code_array.get_next_quad_index()
    code_array.emit("goto", None, None, None)
    p[0] = {
        "starting_quad_index": p[3]["quad_index"],
        "break_quad_index": break_quad_index
    }
    return
예제 #4
0
def run_compiler(input_file_path, output_file_path):
    code = None
    with open(input_file_path, 'r') as input_file:
        code = input_file.read()
    parser.parse(code, lexer=lexer, debug=False, tracking=True)
    code_array.emit("return 0", None, None, None)
    code_generator = CodeGenerator()
    generated_code = code_generator.generate_code()
    with open(output_file_path, 'w') as output_file:
        output_file.write(generated_code)
    return
예제 #5
0
def p_statement_print(p):
    """statement            : PRINT ID
                            | PRINT ID LBRACK expressions RBRACK"""
    symbol_table.check_variable_declaration(p[2], p.slice[2])
    if len(p) == 6:
        var_copy = code_array.setup_array_variable(p[2], p[4], p.slice[2])
        code_array.emit("print", None, var_copy, None)
    else:
        code_array.check_variable_is_not_array(p[2], p.slice[2])
        code_array.emit("print", None, p[2], None)
    return
예제 #6
0
def p_statement_assignment(p):
    """statement            : ID ASSIGNMENT_SIGN expressions
                            | ID LBRACK expressions RBRACK ASSIGNMENT_SIGN expressions"""
    symbol_table.check_variable_declaration(p[1], p.slice[1])
    p[3] = code_array.store_boolean_expression_in_variable(p[3])
    if len(p) == 4:
        code_array.check_variable_is_not_array(p[1], p.slice[1])
        code_array.emit("=", p[1], p[3], None)
    else:
        p[6] = code_array.store_boolean_expression_in_variable(p[6])
        var_copy = code_array.setup_array_variable(p[1], p[3], p.slice[1])
        code_array.emit("=", var_copy, p[6], None)
    return
예제 #7
0
def p_bool_expressions_or(p):
    """bool_expressions     : OR pair"""
    first_arg = p[2]["first_arg"]
    second_arg = p[2]["second_arg"]
    if "t_list" not in first_arg:
        code_array.create_simple_if_check(first_arg)
    if "t_list" not in second_arg:
        p[2]["second_quad_index"] = code_array.create_simple_if_check(
            second_arg)
    temp_var = symbol_table.get_new_temp_variable("bool")
    code_array.emit('=', temp_var, {"value": 1, "type": "bool"}, None)
    code_array.backpatch_e_list(first_arg["t_list"],
                                code_array.get_current_quad_index())
    code_array.emit('goto', None, p[2]["second_quad_index"], None)
    code_array.emit('=', temp_var, {"value": 0, "type": "bool"}, None)
    code_array.backpatch_e_list(first_arg["f_list"],
                                code_array.get_current_quad_index())
    code_array.emit('goto', None, p[2]["second_quad_index"], None)
    code_array.create_simple_if_check(temp_var)
    code_array.backpatch_e_list(second_arg["f_list"],
                                code_array.get_current_quad_index() - 2)
    p[0] = {
        "t_list":
        code_array.merge_e_lists(temp_var["t_list"], second_arg["t_list"]),
        "f_list":
        temp_var["f_list"],
        "type":
        "bool"
    }
    return
예제 #8
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
예제 #9
0
def p_case_element(p):
    """case_element     : CASE NUMCONST COLON qis block
                        | case_element CASE NUMCONST COLON qis block"""
    break_quad_index = code_array.get_next_quad_index()
    code_array.emit("goto", None, None, None)
    if len(p) == 6:
        p[0] = [{
            "num_constraint": p[2],
            "starting_quad_index": p[4]["quad_index"],
            "break_quad_index": break_quad_index
        }]
    else:
        p[0] = [{
            "num_constraint": p[3],
            "starting_quad_index": p[5]["quad_index"],
            "break_quad_index": break_quad_index
        }] + p[1]
    return
예제 #10
0
def p_dec(p):
    """dec      : ID
                | ID LBRACK range RBRACK
                | ID LBRACK NUMCONST RBRACK"""
    p[0] = p[1]
    if len(p) == 2:
        p[0]["is_array"] = False
    else:
        p[0]["is_array"] = True
        if p.slice[3].type == "range":
            p[0]["range"] = p[3]
        if p.slice[3].type == "NUMCONST":
            from_variable = {"value": 0, "type": "int"}
            to_variable = symbol_table.get_new_temp_variable("int")
            code_array.emit("-", to_variable, p[3], {
                "value": 1,
                "type": "int"
            })
            p[0]["range"] = {"from": from_variable, "to": to_variable}
        array_size_variable = symbol_table.get_new_temp_variable("int")
        code_array.emit("-", array_size_variable, p[0]["range"]["to"],
                        p[0]["range"]["from"])
        code_array.emit("+", array_size_variable, array_size_variable, {
            "value": 1,
            "type": "int"
        })
        p[0]["array_size"] = array_size_variable
    return
예제 #11
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
예제 #12
0
def p_statement_switch(p):
    """statement            : SWITCH expressions qis_1 case_element default END
                            | SWITCH expressions qis_1 case_element END"""
    if p[2]["type"] == "bool" and "place" not in p[2] and "value" not in p[2]:
        p[2] = code_array.store_boolean_expression_in_variable(p[2])
        code_array.emit("goto", None,
                        code_array.get_next_quad_index() + 1, None)
        code_array.backpatch_e_list(p[3]["goto_quad_index"],
                                    code_array.get_next_quad_index())
    else:
        code_array.backpatch_e_list(p[3]["goto_quad_index"],
                                    code_array.get_next_quad_index())
    next_list = []
    for case_element in p[4]:
        code_array.emit("==", None, p[2], case_element["num_constraint"])
        code_array.emit("goto", None, case_element["starting_quad_index"],
                        None)
        next_list.append(case_element["break_quad_index"])
    if len(p) == 7:
        code_array.emit("goto", None, p[5]["starting_quad_index"], None)
        next_list.append(p[5]["break_quad_index"])
    code_array.backpatch_e_list(next_list, code_array.get_next_quad_index())
    return
예제 #13
0
def p_bool_expressions_comparator(p):
    """bool_expressions     : LT pair 
                            | LE pair 
                            | GT pair 
                            | GE pair 
                            | EQ pair 
                            | NEQ pair"""
    p[0] = {
        "t_list": [code_array.get_next_quad_index() + 1],
        "f_list": [code_array.get_next_quad_index() + 2],
        "type": "bool"
    }
    opt = p.slice[1].type
    if opt == "EQ":
        opt = "=="
    elif opt == "NEQ":
        opt = "!="
    else:
        opt = p[1]
    code_array.emit(opt, None, p[2]["first_arg"], p[2]["second_arg"])
    code_array.emit("goto", None, None, None)
    code_array.emit("goto", None, None, None)
    return
예제 #14
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
예제 #15
0
def p_statement_for(p):
    """statement            : FOR ID ASSIGNMENT_SIGN counter DO qis_1 statement"""
    symbol_table.check_variable_declaration(p[2], p.slice[2])
    code_array.check_variable_is_not_array(p[2], p.slice[2])
    code_array.emit(p[4]["opt"], p[2], p[2], {"value": 1, "type": "int"})
    code_array.emit("goto", None, code_array.get_next_quad_index() + 2, None)
    code_array.backpatch_e_list(p[6]["goto_quad_index"],
                                code_array.get_next_quad_index())
    code_array.emit("=", p[2], p[4]["from"], None)
    code_array.emit(">", None, p[2], p[4]["to"])
    code_array.emit("goto", None, code_array.get_next_quad_index() + 2, None)
    code_array.emit("goto", None, p[6]["quad_index"], None)
    if p[7] and "exit_when_quad_index" in p[7]:
        code_array.backpatch_e_list(p[7]["exit_when_quad_index"],
                                    code_array.get_next_quad_index())
    return