def p_const_value(p):
    '''const_value :  INTEGER
                |  REAL
                |  CHAR
                |  STRING
                |  SYS_CON
                | true
                | false'''
    p[0] = Node("const_value", p[1])

    p[0].value = p[1]

    if type(p[1]) == int:
        p[0].type = 'integer'

    elif type(p[1]) == float:
        p[0].type = 'real'

    elif type(p[1]) == str:
        p[0].type = 'char'

    if str(p[1]).lower() == 'true':
        p[0].type = 'boolean'
        p[0].value = True

    if str(p[1]).lower() == 'false':
        p[0].type = 'boolean'
        p[0].value = False
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_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_func(p):
    '''factor : SYS_FUNCT
                |  SYS_FUNCT  LP  args_list  RP
    '''
    # TODO
    if len(p) == 2:
        p[0] = Node("p_factor_func", [p[1]])
    else:
        p[0] = Node("p_factor_func", [p[3]])

    p[0].value = None
    p[0].type = None
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
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_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_factor_const(p):
    '''factor :  const_value'''
    p[0] = Node('factor', [p[1]])

    p[0].value = p[1].value
    p[0].type = p[1].type