📄 expr.c
字号:
#include "c.h"
static char rcsid[] = "$Id: expr.c,v 1.1 2002/08/28 23:12:43 drh Exp $";
static char prec[] = {
#define xx(a,b,c,d,e,f,g) c,
#define yy(a,b,c,d,e,f,g) c,
#include "token.h"
};
static int oper[] = {
#define xx(a,b,c,d,e,f,g) d,
#define yy(a,b,c,d,e,f,g) d,
#include "token.h"
};
float refinc = 1.0;
static Tree expr2(void);
static Tree expr3(int);
static Tree nullcheck(Tree);
static Tree postfix(Tree);
static Tree unary(void);
static Tree primary(void);
static Type super(Type ty);
static Type super(Type ty) {
switch (ty->op) {
case INT:
if (ty->size < inttype->size)
return inttype;
break;
case UNSIGNED:
if (ty->size < unsignedtype->size)
return unsignedtype;
break;
case POINTER:
return unsignedptr;
}
return ty;
}
Tree expr(int tok) {
static char stop[] = { IF, ID, '}', 0 };
Tree p = expr1(0);
while (t == ',') {
Tree q;
t = gettok();
q = pointer(expr1(0));
p = tree(RIGHT, q->type, root(value(p)), q);
}
if (tok)
test(tok, stop);
return p;
}
Tree expr0(int tok) {
return root(expr(tok));
}
Tree expr1(int tok) {
static char stop[] = { IF, ID, 0 };
Tree p = expr2();
if (t == '='
|| (prec[t] >= 6 && prec[t] <= 8)
|| (prec[t] >= 11 && prec[t] <= 13)) {
int op = t;
t = gettok();
if (oper[op] == ASGN)
p = asgntree(ASGN, p, value(expr1(0)));
else
{
expect('=');
p = incr(op, p, expr1(0));
}
}
if (tok)
test(tok, stop);
return p;
}
Tree incr(int op, Tree v, Tree e) {
return asgntree(ASGN, v, (*optree[op])(oper[op], v, e));
}
static Tree expr2(void) {
Tree p = expr3(4);
if (t == '?') {
Tree l, r;
Coordinate pts[2];
if (Aflag > 1 && isfunc(p->type))
warning("%s used in a conditional expression\n",
funcname(p));
p = pointer(p);
t = gettok();
pts[0] = src;
l = pointer(expr(':'));
pts[1] = src;
r = pointer(expr2());
if (generic(p->op) != CNST && events.points)
{
apply(events.points, &pts[0], &l);
apply(events.points, &pts[1], &r);
}
p = condtree(p, l, r);
}
return p;
}
Tree value(Tree p) {
int op = generic(rightkid(p)->op);
if (p->type != voidtype
&& (op==AND || op==OR || op==NOT || op==EQ || op==NE
|| op== LE || op==LT || op== GE || op==GT))
p = condtree(p, consttree(1, inttype),
consttree(0, inttype));
return p;
}
static Tree expr3(int k) {
int k1;
Tree p = unary();
for (k1 = prec[t]; k1 >= k; k1--)
while (prec[t] == k1 && *cp != '=') {
Tree r;
Coordinate pt;
int op = t;
t = gettok();
pt = src;
p = pointer(p);
if (op == ANDAND || op == OROR) {
r = pointer(expr3(k1));
if (events.points)
apply(events.points, &pt, &r);
} else
r = pointer(expr3(k1 + 1));
p = (*optree[op])(oper[op], p, r);
}
return p;
}
static Tree unary(void) {
Tree p;
switch (t) {
case '*': t = gettok(); p = unary(); p = pointer(p);
if (isptr(p->type)
&& (isfunc(p->type->type) || isarray(p->type->type)))
p = retype(p, p->type->type);
else {
if (YYnull)
p = nullcheck(p);
p = rvalue(p);
} break;
case '&': t = gettok(); p = unary(); if (isarray(p->type) || isfunc(p->type))
p = retype(p, ptr(p->type));
else
p = lvalue(p);
if (isaddrop(p->op) && p->u.sym->sclass == REGISTER)
error("invalid operand of unary &; `%s' is declared register\n", p->u.sym->name);
else if (isaddrop(p->op))
p->u.sym->addressed = 1;
break;
case '+': t = gettok(); p = unary(); p = pointer(p);
if (isarith(p->type))
p = cast(p, promote(p->type));
else
typeerror(ADD, p, NULL); break;
case '-': t = gettok(); p = unary(); p = pointer(p);
if (isarith(p->type)) {
Type ty = promote(p->type);
p = cast(p, ty);
if (isunsigned(ty)) {
warning("unsigned operand of unary -\n");
p = simplify(ADD, ty, simplify(BCOM, ty, p, NULL), cnsttree(ty, 1UL));
} else
p = simplify(NEG, ty, p, NULL);
} else
typeerror(SUB, p, NULL); break;
case '~': t = gettok(); p = unary(); p = pointer(p);
if (isint(p->type)) {
Type ty = promote(p->type);
p = simplify(BCOM, ty, cast(p, ty), NULL);
} else
typeerror(BCOM, p, NULL); break;
case '!': t = gettok(); p = unary(); p = pointer(p);
if (isscalar(p->type))
p = simplify(NOT, inttype, cond(p), NULL);
else
typeerror(NOT, p, NULL); break;
case INCR: t = gettok(); p = unary(); p = incr(INCR, pointer(p), consttree(1, inttype)); break;
case DECR: t = gettok(); p = unary(); p = incr(DECR, pointer(p), consttree(1, inttype)); break;
case TYPECODE: case SIZEOF: { int op = t;
Type ty;
p = NULL;
t = gettok();
if (t == '(') {
t = gettok();
if (istypename(t, tsym)) {
ty = typename();
expect(')');
} else {
p = postfix(expr(')'));
ty = p->type;
}
} else {
p = unary();
ty = p->type;
}
assert(ty);
if (op == TYPECODE)
p = cnsttree(inttype, (long)ty->op);
else {
if (isfunc(ty) || ty->size == 0)
error("invalid type argument `%t' to `sizeof'\n", ty);
else if (p && rightkid(p)->op == FIELD)
error("`sizeof' applied to a bit field\n");
p = cnsttree(unsignedlong, (unsigned long)ty->size);
} } break;
case '(':
t = gettok();
if (istypename(t, tsym)) {
Type ty, ty1 = typename(), pty;
expect(')');
ty = unqual(ty1);
if (isenum(ty)) {
Type ty2 = ty->type;
if (isconst(ty1))
ty2 = qual(CONST, ty2);
if (isvolatile(ty1))
ty2 = qual(VOLATILE, ty2);
ty1 = ty2;
ty = ty->type;
}
p = pointer(unary());
pty = p->type;
if (isenum(pty))
pty = pty->type;
if (isarith(pty) && isarith(ty)
|| isptr(pty) && isptr(ty)) {
explicitCast++;
p = cast(p, ty);
explicitCast--;
} else if (isptr(pty) && isint(ty)
|| isint(pty) && isptr(ty)) {
if (Aflag >= 1 && ty->size < pty->size)
warning("conversion from `%t' to `%t' is compiler dependent\n", p->type, ty);
p = cast(p, ty);
} else if (ty != voidtype) {
error("cast from `%t' to `%t' is illegal\n",
p->type, ty1);
ty1 = inttype;
}
if (generic(p->op) == INDIR || ty->size == 0)
p = tree(RIGHT, ty1, NULL, p);
else
p = retype(p, ty1);
} else
p = postfix(expr(')'));
break;
default:
p = postfix(primary());
}
return p;
}
static Tree postfix(Tree p) {
for (;;)
switch (t) {
case INCR: p = tree(RIGHT, p->type,
tree(RIGHT, p->type,
p,
incr(t, p, consttree(1, inttype))),
p);
t = gettok(); break;
case DECR: p = tree(RIGHT, p->type,
tree(RIGHT, p->type,
p,
incr(t, p, consttree(1, inttype))),
p);
t = gettok(); break;
case '[': {
Tree q;
t = gettok();
q = expr(']');
if (YYnull)
if (isptr(p->type))
p = nullcheck(p);
else if (isptr(q->type))
q = nullcheck(q);
p = (*optree['+'])(ADD, pointer(p), pointer(q));
if (isptr(p->type) && isarray(p->type->type))
p = retype(p, p->type->type);
else
p = rvalue(p);
} break;
case '(': {
Type ty;
Coordinate pt;
p = pointer(p);
if (isptr(p->type) && isfunc(p->type->type))
ty = p->type->type;
else {
error("found `%t' expected a function\n", p->type);
ty = func(voidtype, NULL, 1);
p = retype(p, ptr(ty));
}
pt = src;
t = gettok();
p = call(p, ty, pt);
} break;
case '.': t = gettok();
if (t == ID) {
if (isstruct(p->type)) {
Tree q = addrof(p);
p = field(q, token);
q = rightkid(q);
if (isaddrop(q->op) && q->u.sym->temporary)
p = tree(RIGHT, p->type, p, NULL);
} else
error("left operand of . has incompatible type `%t'\n",
p->type);
t = gettok();
} else
error("field name expected\n"); break;
case DEREF: t = gettok();
p = pointer(p);
if (t == ID) {
if (isptr(p->type) && isstruct(p->type->type)) {
if (YYnull)
p = nullcheck(p);
p = field(p, token);
} else
error("left operand of -> has incompatible type `%t'\n", p->type);
t = gettok();
} else
error("field name expected\n"); break;
default:
return p;
}
}
static Tree primary(void) {
Tree p;
assert(t != '(');
switch (t) {
case ICON:
case FCON: p = tree(mkop(CNST,tsym->type), tsym->type, NULL, NULL);
p->u.v = tsym->u.c.v;
break;
case SCON: if (ischar(tsym->type->type))
tsym->u.c.v.p = stringn(tsym->u.c.v.p, tsym->type->size);
else
tsym->u.c.v.p = memcpy(allocate((tsym->type->size/widechar->size)*sizeof (int), PERM),
tsym->u.c.v.p, (tsym->type->size/widechar->size)*sizeof (int));
tsym = constant(tsym->type, tsym->u.c.v);
if (tsym->u.c.loc == NULL)
tsym->u.c.loc = genident(STATIC, tsym->type, GLOBAL);
p = idtree(tsym->u.c.loc); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -