⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 expr.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
     * However K&R mandates that all floating point arithmetic be done as
     * doubles.
     */
    tp = tp_float;
    if (is_same_type (tp1, tp) || is_same_type (tp2, tp)) {
	if (lang_option == LANG_KANDR) {
	    tp = tp_double;
	}
	*node2 = implicit_castop (ep2, tp);
	*node1 = implicit_castop (ep1, tp);
	return tp;
    }
    /*
     * The integral promotions are performed on both operands.
     * If an int can represent all values of the original type, the value is
     * converted to an int; otherwise it is converted to an unsigned int.
     */
    ep1 = integral_promotion (ep1);
    tp1 = ep1->etp;
    ep2 = integral_promotion (ep2);
    tp2 = ep2->etp;

    /* 
     * is both operands have the same type, then no further
     * conversion is needed.
     */
    if (is_same_type (tp1, tp2)) {
	*node2 = ep2;
	*node1 = ep1;
	return tp1;
    }
    /*
     *if either operand has type unsigned long long int, the other operand
     * is converted to unsigned long long int
     */
    tp = tp_ulonglong;
    if (is_same_type (tp1, tp) || is_same_type (tp2, tp)) {
	*node2 = implicit_castop (ep2, tp);
	*node1 = implicit_castop (ep1, tp);
	return tp;
    }
    /*
     *if either operand has type long long int, the other operand
     * is converted to long long int
     */
    tp = tp_longlong;
    if (is_same_type (tp1, tp) || is_same_type (tp2, tp)) {
	*node2 = implicit_castop (ep2, tp);
	*node1 = implicit_castop (ep1, tp);
	return tp;
    }
    /*
     * if either operand has type unsigned long int, the other operand is
     * converted to unsigned long int.
     */
    tp = tp_ulong;
    if (is_same_type (tp1, tp) || is_same_type (tp2, tp)) {
	*node2 = implicit_castop (ep2, tp);
	*node1 = implicit_castop (ep1, tp);
	return tp;
    }
    /*
     * if one operand has type long int and the other has type unsigned int,
     * if a long int can represent all values of an unsigned int, the operand
     * of type unsigned int is converted to long int;  if a long int cannot
     * represent all the values of an unsigned int, both operands are converted
     * to unsigned long int.
     */
    if ((tp1->type == bt_long && is_same_type (tp2, tp_uint)) ||
	(tp2->type == bt_long && is_same_type (tp1, tp_uint))) {
	tp = (tp_long->size > tp_uint->size) ? tp_long : tp_ulong;
	*node2 = implicit_castop (ep2, tp);
	*node1 = implicit_castop (ep1, tp);
	return tp;
    }
    /*
     * if either operand has type long int, the other operand is
     * converted to long int.
     */
    tp = tp_long;
    if (is_same_type (tp1, tp) || is_same_type (tp2, tp)) {
	*node2 = implicit_castop (ep2, tp);
	*node1 = implicit_castop (ep1, tp);
	return tp;
    }
    /*
     * if either operand has type unsigned int, the other operand is
     * converted to unsigned int.
     */
    tp = tp_uint;
    if (is_same_type (tp1, tp) || is_same_type (tp2, tp)) {
	*node2 = implicit_castop (ep2, tp);
	*node1 = implicit_castop (ep1, tp);
	return tp;
    }
    /*
     * both operands have type int
     */
    tp = tp_int;
    *node2 = implicit_castop (ep2, tp);
    *node1 = implicit_castop (ep1, tp);
    return tp;
}

/*
 * ,,arithmetic_conversion'' for comparisons:
 * When comparing two char's, it is not necessary to cast
 * both of them to long in advance
 *
 * Perhaps not strictly K&R, but more efficient.
 * If you don't like it, use arithmetic_conversion in ALL cases
 */
static TYP *arithmetic_conversion2 P2 (EXPR **, node1, EXPR **, node2)
{
    TYP    *tp1 = (*node1)->etp;
    TYP    *tp2 = (*node2)->etp;
    TYP    *tp;

    /* short cut: */
    if (is_same_type (tp1, tp2)) {
	return tp1;
    }
    /* comparison with integer constant */
    *node1 = opt0 (*node1);
    *node2 = opt0 (*node2);
    if (is_constexpr (*node1)) {
	EXPR  **node = node1;

	tp = tp1;
	node1 = node2;
	tp1 = tp2;
	node2 = node;
	tp2 = tp;
    }
    if (is_constexpr (*node2)) {
#ifndef SYNTAX_CORRECT
	if (is_pointer_type (tp2) && !is_pointer_type (tp1)
	    && !is_null_pointer (*node2)) {
	    message (ERR_MISMATCH);
	}
#endif /* SYNTAX_CORRECT */
	if (is_constant_in_range (*node2, tp1)) {
	    tp = tp1;
	    *node2 = implicit_castop (*node2, tp);
	    return tp;
	}
    }
    switch (tp1->type) {
	/* Type of first operand */
    case bt_char:
    case bt_schar:
	switch (tp2->type) {
	case bt_char:
	case bt_schar:
	    return tp2;
	case bt_charu:
	case bt_uchar:
	    tp = tp_short;
	    *node1 = implicit_castop (*node1, tp);
	    *node2 = implicit_castop (*node2, tp);
	    return tp;
	case bt_short:
	case bt_ushort:
	case bt_int16:
	case bt_uint16:
	case bt_int32:
	case bt_uint32:
	case bt_long:
	case bt_ulong:
	case bt_longlong:
	case bt_ulonglong:
	case bt_float:
	case bt_double:
	case bt_longdouble:
	    tp = tp2;
	    *node1 = implicit_castop (*node1, tp);
	    return tp;
	default:
	    break;
	}
	break;
    case bt_charu:
    case bt_uchar:
	switch (tp2->type) {
	case bt_charu:
	case bt_uchar:
	    return tp2;
	case bt_char:
	case bt_schar:
	    tp = tp_short;
	    *node1 = implicit_castop (*node1, tp);
	    *node2 = implicit_castop (*node2, tp);
	    return tp;
	case bt_short:
	case bt_ushort:
	case bt_int16:
	case bt_uint16:
	case bt_int32:
	case bt_uint32:
	case bt_long:
	case bt_ulong:
	case bt_longlong:
	case bt_ulonglong:
	case bt_float:
	case bt_double:
	case bt_longdouble:
	    tp = tp2;
	    *node1 = implicit_castop (*node1, tp);
	    return tp;
	default:
	    break;
	}
	break;
    case bt_short:
    case bt_ushort:
    case bt_int16:
    case bt_uint16:
	switch (tp2->type) {
	case bt_char:
	case bt_charu:
	case bt_uchar:
	case bt_schar:
	    tp = tp1;
	    *node2 = implicit_castop (*node2, tp);
	    return tp;
	case bt_ushort:
	case bt_uint16:
	    if (tp_int->size == tp2->size) {
		tp = tp2;
		*node1 = implicit_castop (*node1, tp);
	    } else {
		tp = tp_long;
		*node1 = implicit_castop (*node1, tp);
		*node2 = implicit_castop (*node2, tp);
	    }
	    return tp;
	case bt_short:
	case bt_int16:
	    if (tp_int->size == tp2->size) {
		tp = tp_ushort;
		*node2 = implicit_castop (*node2, tp);
	    } else {
		tp = tp_long;
		*node1 = implicit_castop (*node1, tp);
		*node2 = implicit_castop (*node2, tp);
	    }
	    return tp;
	case bt_int32:
	case bt_uint32:
	case bt_long:
	case bt_ulong:
	case bt_longlong:
	case bt_ulonglong:
	case bt_float:
	case bt_double:
	case bt_longdouble:
	    tp = tp2;
	    *node1 = implicit_castop (*node1, tp);
	    return tp;
	default:
	    break;
	}
	break;
	/*
	 * pointers are equivalent to function names
	 */
    case bt_pointer16:
    case bt_pointer32:
	if (is_func (tp2)) {
	    tp = tp1;
	    *node2 = implicit_castop (*node2, tp);
	    return tp;
	}
	/*lint -fallthrough */
    case bt_func:
	if (is_pointer_type (tp2)) {
	    *node1 = implicit_castop (*node1, tp2);
	}
	/*lint -fallthrough */
    case bt_int32:
    case bt_uint32:
    case bt_long:
    case bt_ulong:
	switch (tp2->type) {
	case bt_char:
	case bt_charu:
	case bt_uchar:
	case bt_schar:
	case bt_short:
	case bt_ushort:
	case bt_int16:
	case bt_uint16:
	case bt_pointer16:
	case bt_int32:
	case bt_long:
	    tp = tp1;
	    *node2 = implicit_castop (*node2, tp);
	    return tp;
	case bt_uint32:
	case bt_ulong:
	case bt_pointer32:
	case bt_longlong:
	case bt_ulonglong:
	case bt_float:
	case bt_double:
	case bt_longdouble:
	    tp = tp2;
	    *node1 = implicit_castop (*node1, tp);
	    return tp;
	default:
	    break;
	}
	break;
    case bt_longlong:
    case bt_ulonglong:
	switch (tp2->type) {
	case bt_char:
	case bt_charu:
	case bt_uchar:
	case bt_schar:
	case bt_short:
	case bt_ushort:
	case bt_int16:
	case bt_uint16:
	case bt_pointer16:
	case bt_int32:
	case bt_long:
	    tp = tp1;
	    *node2 = implicit_castop (*node2, tp);
	    return tp;
	case bt_uint32:
	case bt_ulong:
	case bt_pointer32:
	case bt_longlong:
	case bt_ulonglong:
	case bt_float:
	case bt_double:
	case bt_longdouble:
	    tp = tp2;
	    *node1 = implicit_castop (*node1, tp);
	    return tp;
	default:
	    break;
	}
	break;
    case bt_float:
	switch (tp2->type) {
	case bt_char:
	case bt_charu:
	case bt_uchar:
	case bt_schar:
	case bt_short:
	case bt_ushort:
	case bt_int16:
	case bt_uint16:
	case bt_int32:
	case bt_uint32:
	case bt_long:
	case bt_ulong:
	case bt_longlong:
	case bt_ulonglong:
	    tp = tp1;
	    *node2 = implicit_castop (*node2, tp);
	    return tp;
	case bt_float:
	case bt_double:
	case bt_longdouble:
	    tp = tp2;
	    *node1 = implicit_castop (*node1, tp);
	    return tp;
	default:
	    break;
	}
	break;
    case bt_double:
	switch (tp2->type) {
	case bt_char:
	case bt_charu:
	case bt_uchar:
	case bt_schar:
	case bt_short:
	case bt_ushort:
	case bt_int16:
	case bt_uint16:
	case bt_int32:
	case bt_uint32:
	case bt_long:
	case bt_ulong:
	case bt_longlong:
	case bt_ulonglong:
	case bt_float:
	    tp = tp1;
	    *node2 = implicit_castop (*node2, tp);
	    return tp;
	case bt_double:
	case bt_longdouble:
	    tp = tp2;
	    *node1 = implicit_castop (*node1, tp);
	    return tp;
	default:
	    break;
	}
	break;
    case bt_longdouble:
	switch (tp2->type) {
	case bt_char:
	case bt_charu:
	case bt_uchar:
	case bt_schar:
	case bt_short:
	case bt_ushort:
	case bt_int16:
	case bt_uint16:
	case bt_int32:
	case bt_uint32:
	case bt_long:
	case bt_ulong:
	case bt_longlong:
	case bt_ulonglong:
	case bt_float:
	case bt_double:
	case bt_longdouble:
	    tp = tp2;
	    *node1 = implicit_castop (*node1, tp);
	    return tp;
	default:
	    break;
	}
	break;
    default:
	break;
    }
#ifndef SYNTAX_CORRECT
    message (ERR_MISMATCH);
#endif /* SYNTAX_CORRECT */
    return tp1;
}


/*
 * multops parses the multiply priority operators. the syntax of this group
 * is:
 *
 * unary multop * unary multop / unary multop % unary
 */
static EXPR *multops P0 (void)
{
    EXPR   *ep1, *ep2;
    EXPRTYPE nt;
    TYP    *tp;

    ep1 = unary ();
    if (ep1 == NIL_EXPR) {
	return NIL_EXPR;
    }
    for (;;) {
	switch (lastst) {
	case tk_star:
	    nt = en_mul;
	    break;
	case tk_divide:
	    nt = en_div;
	    break;
	case tk_mod:
	    nt = en_mod;
	    break;
	default:
	    ep1 = opt0 (ep1);
	    return ep1;
	}
	getsym ();		/* move on to next unary op */
	ep2 = unary ();
	if (ep2) {
	    switch (nt) {
	    case en_div:
		check_zero (ep2);
		/*lint -fallthrough */
	    case en_mul:
		check_arithmetic (ep1);
		check_arithmetic (ep2);
		break;
	    case en_mod:
		check_zero (ep2);
		check_integral (ep1);
		check_integral (ep2);
		break;
	    default:
		CANNOT_REACH_HERE ();
		break;
	    }
	    check_set (ep1);
	    check_set (ep2);
	    check_sequence_accessed (ep1);
	    check_sequence_accessed (ep2);
	    tp = arithmetic_conversion (&ep1, &ep2);
	    ep1 = mk_node (nt, ep1, ep2, tp);
#ifndef SYNTAX_CORRECT
	} else {
	    message (ERR_IDEXPECT);
#endif /* SYNTAX_CORRECT */
	}
    }
}

/*
 * addops handles the addition and subtraction operators.
 */
static EXPR *addops P0 (void)
{
    EXPR   *ep1, *ep2, *ep3;
    TYP    *tp;
    TYP    *tp1 = is_same_size (tp_pointer, tp_ulong) ? tp_long : tp_short;
    EXPRTYPE nt;

    ep1 = multops ();
#ifndef SYNTAX_CORRECT
    if (ep1 == NIL_EXPR) {
	return NIL_EXPR;
    }
#endif /* SYNTAX_CORRECT */
    for (;;) {
	switch (lastst) {
	case tk_plus:
	    nt = en_add;
	    break;
	case tk_minus:
	    nt = en_sub;
	    break;
	default:
	    ep1 = opt0 (ep1);
	    return ep1;
	}
	getsym ();
	ep2 = multops ();
#ifndef SYNTAX_CORRECT
	if (ep2 == NIL_EXPR) {
	    message (ERR_IDEXPECT);
	    return ep2;
	}
	check_set (ep1);
	check_set (ep2);
	check_sequence_accessed (ep1);
	check_sequence_accessed (ep2);
#endif /* SYNTAX_CORRECT */
	if (is_pointer_type (ep1->etp)) {
	    if ((nt == en_sub) && is_pointer_type (ep2->etp)) {
		/* pointer subtraction */
#ifndef SYNTAX_CORRECT
		if (!is_compatible_type (ep1->etp, ep2->etp)) {
		    message (WARN_POINTER);
		}
#endif /* SYNTAX_CORRECT */
		check_object (ep1);
		check_complete (ep1->etp);
		check_object (ep2);
		check_complete (ep2->etp);
		ep1

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -