def p_expr(p):
    '''expr :  expr  PLUS  term
                |  expr  MINUS  term
                |  expr  OR  term
                |  term'''
    if len(p) == 2:
        p[0] = Node("expr-term", [p[1]])

        if hasattr(p[1], 'symbol'):
            p[0].symbol = p[1].symbol
        else:
            p[0].value = p[1].value
            p[0].type = p[1].type

    else:
        p[0] = Node("expr-expr", [p[1], p[3]])

        if p[2] == 'or':
            symbol = table.get_temp('boolean')
        else:
            print(type_of_node(p[1]))
            print(type_of_node(p[3]))

            if type_of_node(p[1]) == 'real' or type_of_node(p[3]) == 'real':
                symbol = table.get_temp('real')
            else:
                symbol = table.get_temp('integer')

        emit(p[2], symbol, p[1], p[3])
        p[0].symbol = symbol
def p_factor_not(p):
    '''factor :  NOT factor'''

    p[0] = Node("factor", [p[2]])

    symbol = table.get_temp(type_of_node(p[2]))
    emit('NOT', symbol, p[2])
    p[0].symbol = symbol
def p_factor_minus(p):
    '''factor :  MINUS factor'''

    p[0] = Node("factor", [p[2]])

    symbol = table.get_temp(type_of_node(p[2]))
    emit('-', symbol, 0, p[2])
    p[0].symbol = symbol
def p_factor_1(p):
    '''factor :    LP  expression  RP '''
    p[0] = Node("factor", [p[2]])

    if hasattr(p[2], 'symbol'):
        p[0].symbol = p[2].symbol
    else:
        p[0].value = p[2].value
        p[0].type = p[2].type
def p_factor_array(p):
    '''factor : NAME LB expression RB '''
    # FIXME: 这个地方只有可能是在右边的数组索引,而不是左边的,所以将内容载入到临时变量里面吧
    p[0] = Node("p_factor_array", [p[3]])
    # FIXME: 也需要创建一个临时变量

    symbol = table.get_identifier(p[1])
    symbol = table.get_temp(type_of_node(symbol))
    emit('LOADREF', symbol, p[1], p[3])
    p[0].symbol = symbol
def p_term(p):
    '''term :  term  MUL  factor
                |  term  DIV  factor
                |  term  MOD  factor
                |  term  AND  factor
                |  factor'''
    if len(p) == 2:
        p[0] = Node("term-factor", [p[1]])

        if hasattr(p[1], 'symbol'):
            p[0].symbol = p[1].symbol
        else:
            p[0].value = p[1].value
            p[0].type = p[1].type

    else:
        p[0] = Node("term-term", [p[1], p[3]])

        if p[2] == '*':
            if type_of_node(p[1]) == 'real' or type_of_node(p[3]) == 'real':
                symbol = table.get_temp('real')
            else:
                symbol = table.get_temp('integer')

        elif p[2] == '/':
            symbol = table.get_temp('real')

        elif p[2].lower() in ['div', 'mod']:
            # pascal 语言里 div 和 / 是不同的
            # div 表示整除,总得到一个整数
            # / 表示浮点数除,总得到一个浮点数
            if type_of_node(p[1]) != 'integer':
                raise ValueError('Type mismatch: %s' % type_of_node(p[1]))
            if type_of_node(p[3]) != 'integer':
                raise ValueError('Type mismatch: %s' % type_of_node(p[3]))
            symbol = table.get_temp('integer')

        elif p[2].lower() == 'and':
            symbol = table.get_temp('boolean')

        emit(p[2], symbol, p[1], p[3])
        p[0].symbol = symbol
def p_factor_name(p):
    '''factor :  NAME'''
    p[0] = Node('factor', [p[1]])

    symbol = table.get_identifier(p[1])

    if symbol.var_function == 'function':
        if table.scope().name.endswith('.' + symbol.name):
            symbol = table.get_identifier('_return')

    p[0].symbol = symbol
def p_for_label1(p):
    '''for_label1 :  '''
    p[0] = Node("", [])

    symbol = table.get_identifier(p[-6])
    emit('+', symbol, p[-4], 0)

    p[0].label1 = table.get_label()
    p[0].label2 = table.get_label()
    p[0].symbol = symbol

    emit('LABEL', p[0].label1)
def p_factor_2(p):
    '''factor : NAME  DOT  NAME'''

    p[0] = Node("p_factor_1", [p[1], p[2], p[3]])
    symbol = table.get_identifier(p[1])
    params = symbol.get_params()
    try:
        symbol = table.get_temp(
            [a_tuple for a_tuple in params if a_tuple[0] == p[3]][0][1])
    except IndexError:
        raise ValueError("Dot index error")
    emit('LOADREF', symbol, p[1], p[3])
    p[0].symbol = symbol
def p_expression(p):
    '''expression :  expression  GE  expr
                |  expression  GT  expr
                |  expression  LE  expr
                |  expression  LT  expr
                |  expression  EQUAL  expr
                |  expression  UNEQUAL  expr
                |  expr'''
    if len(p) == 2:
        p[0] = Node("expression", [p[1]])

        if hasattr(p[1], 'symbol'):
            p[0].symbol = p[1].symbol
        else:
            p[0].value = p[1].value
            p[0].type = p[1].type

    else:
        p[0] = Node("expression", [p[1], p[3]])

        symbol = table.get_temp('boolean')
        emit(p[2], symbol, p[1], p[3])
        p[0].symbol = symbol
def p_function_head(p):
    '''function_head :  FUNCTION  function_name  parameters  COLON  simple_type_decl '''
    p[0] = Node("function_head", [p[3], p[5]])

    for name, type, reference in p[3].list:
        table.define(name, type, reference=reference)
    table.define('_return', p[5].type, 'var', p[3].list)

    table.scope().return_type = p[5].type
    table.get_identifier(p[2].name).type = p[5].type
    table.get_identifier(p[2].name).params = p[3].list

    symbol = table.get_identifier('_return')
    p[0].symbol = symbol
    emit("LABEL", p[2].name, table.scope().name)
def p_factor_function(p):
    '''factor : NAME  LP  args_list  RP'''
    # TODO
    p[0] = Node("p_factor_function", [p[3]])

    function = table.get_identifier(p[1])

    p[0].value = None
    p[0].type = function.type

    for item, param in zip(p[3].list, function.params):
        if param[2]:
            emit("REFER", None, item)
        else:
            emit("PARAM", None, item)

    symbol = table.get_temp(p[0].type)
    emit("CALL", symbol, p[1], table.get_identifier_scope(p[1]))
    p[0].symbol = symbol