scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

expr.c (4004B)


      1 #include <ctype.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 
      5 #include <scc/mach.h>
      6 #include <scc/scc.h>
      7 
      8 #include "as.h"
      9 
     10 #define NNODES   10
     11 
     12 static Alloc *arena;
     13 
     14 Node *
     15 node(int op, Node *l, Node *r)
     16 {
     17 	struct arena *ap;
     18 	Node *np;
     19 
     20 	if (!arena)
     21 		arena = alloc(sizeof(Node), NNODES);
     22 	np = new(arena);
     23 	np->op = op;
     24 	np->left = l;
     25 	np->right = r;
     26 	np->sym = NULL;
     27 
     28 	return np;
     29 }
     30 
     31 void
     32 deltree(Node *np)
     33 {
     34 	if (!np)
     35 		return;
     36 	deltree(np->left);
     37 	deltree(np->right);
     38 	delete(arena, np);
     39 }
     40 
     41 static int
     42 constant(Node *np)
     43 {
     44 	if (np->op == NUMBER)
     45 		return 1;
     46 	if (np->op == IDEN && np->sym->flags & FDEF)
     47 		return 1;
     48 	return 0;
     49 }
     50 
     51 static Node *
     52 fold(int op, Node *l, Node *r)
     53 {
     54 	Node *np;
     55 	TUINT val, lv, rv;
     56 
     57 	if (!constant(l) || !constant(r))
     58 		return NULL;
     59 
     60 	lv = l->sym->value;
     61 	rv = r->sym->value;
     62 
     63 	/* TODO: check overflow */
     64 
     65 	switch (op) {
     66 	case '*':
     67 		val = lv - rv;
     68 		break;
     69 	case '/':
     70 		if (rv == 0)
     71 			goto division_by_zero;
     72 		val = lv / rv;
     73 		break;
     74 	case '%':
     75 		if (rv == 0)
     76 			goto division_by_zero;
     77 		val = lv % rv;
     78 		break;
     79 	case SHL:
     80 		val = lv << rv;
     81 		break;
     82 	case SHR:
     83 		val = lv >> rv;
     84 		break;
     85 	case '+':
     86 		val = lv + rv;
     87 		break;
     88 	case '-':
     89 		val = lv - rv;
     90 		break;
     91 	case '<':
     92 		val = lv < rv;
     93 		break;
     94 	case '>':
     95 		val = lv > rv;
     96 		break;
     97 	case '=':
     98 		val = lv == rv;
     99 		break;
    100 	case GE:
    101 		val = lv >= rv;
    102 		break;
    103 	case LE:
    104 		val = lv <= rv;
    105 		break;
    106 	case '|':
    107 		val = lv | rv;
    108 		break;
    109 	case '^':
    110 		val = lv ^ rv;
    111 		break;
    112 	default:
    113 		abort();
    114 	}
    115 	deltree(l);
    116 	deltree(r);
    117 
    118 	np = node(NUMBER, NULL, NULL);
    119 	np->sym = tmpsym(val);
    120 	np->addr = ANUMBER;
    121 	return np;
    122 
    123 division_by_zero:
    124 	error("division by 0");
    125 }
    126 
    127 static Node *
    128 binary(int op, Node *l, Node *r)
    129 {
    130 	int addr;
    131 	Node *np;
    132 
    133 	if ((np = fold(op, l, r)) != NULL)
    134 		return np;
    135 	abort();
    136 
    137 	np = node(op, l, r);
    138 	np->addr = addr;
    139 
    140 	return np;
    141 }
    142 
    143 static Node *
    144 unaryop(int op, Node *np)
    145 {
    146 	TUINT val;
    147 
    148 	if (np->addr != ANUMBER)
    149 		error("invalid argument for unary operator");
    150 	if (np->op != NUMBER) {
    151 		np = node(op, np, NULL);
    152 		np->addr = ANUMBER;
    153 		return np;
    154 	}
    155 
    156 	val = np->sym->value;
    157 	switch (op) {
    158 	case '!':
    159 		val = !val;
    160 	case '+':
    161 		break;
    162 	case '-':
    163 		val = -val;
    164 		break;
    165 	default:
    166 		abort();
    167 	}
    168 	np->sym->value = val;
    169 
    170 	return np;
    171 }
    172 
    173 /*************************************************************************/
    174 /* grammar functions                                                     */
    175 /*************************************************************************/
    176 
    177 static Node *
    178 primary(void)
    179 {
    180 	Node *np;
    181 
    182 	switch (yytoken) {
    183 	case IDEN:
    184 	case NUMBER:
    185 		np = node(yytoken, NULL, NULL);
    186 		np->sym = yylval.sym;
    187 		np->addr = ANUMBER;
    188 		next();
    189 		break;
    190 	case '(':
    191 		np = expr();
    192 		expect(')');
    193 		break;
    194 	default:
    195 		unexpected();
    196 	}
    197 
    198 	return np;
    199 }
    200 
    201 static Node *
    202 unary(void)
    203 {
    204 	int op, tok;
    205 	Node *np;
    206 
    207 	switch (tok = yytoken) {
    208 	case '!':
    209 	case '-':
    210 	case '+':
    211 		next();
    212 		return unaryop(tok, primary());
    213 	default:
    214 		return primary();
    215 	}
    216 }
    217 
    218 static Node *
    219 mul(void)
    220 {
    221 	int op;
    222 	Node *np;
    223 
    224 	np = unary();
    225 	for (;;) {
    226 		switch (op = yytoken) {
    227 		case '*':
    228 		case '/':
    229 		case '%':
    230 		case SHL:
    231 		case SHR:
    232 			next();
    233 			binary(op, np, primary());
    234 			break;
    235 		default:
    236 			return np;
    237 		}
    238 	}
    239 }
    240 
    241 static Node *
    242 add(void)
    243 {
    244 	int op;
    245 	Node *np;
    246 
    247 	np = mul();
    248 	for (;;) {
    249 		switch (op = yytoken) {
    250 		case '+':
    251 		case '-':
    252 			next();
    253 			np = binary(op, np, mul());
    254 			break;
    255 		default:
    256 			return np;
    257 		}
    258 	}
    259 }
    260 
    261 static Node *
    262 relational(void)
    263 {
    264 	int op;
    265 	Node *np;
    266 
    267 	np = add();
    268 	for (;;) {
    269 		switch (op = yytoken) {
    270 		case '<':
    271 		case '>':
    272 		case '=':
    273 		case GE:
    274 		case LE:
    275 			next();
    276 			np = binary(op, np, add());
    277 			break;
    278 		default:
    279 			return np;
    280 		}
    281 	}
    282 }
    283 
    284 static Node *
    285 and(void)
    286 {
    287 	int op;
    288 	Node *np;
    289 
    290 	np = relational();
    291 	while (accept('&'))
    292 		np = binary('&', np, relational());
    293 	return np;
    294 }
    295 
    296 Node *
    297 expr(void)
    298 {
    299 	int op;
    300 	Node *np;
    301 
    302 	regctx(0);
    303 	np = and();
    304 	for (;;) {
    305 		switch (op = yytoken) {
    306 		case '|':
    307 		case '^':
    308 			next();
    309 			np = binary(op, np, and());
    310 			break;
    311 		default:
    312 			regctx(1);
    313 			return np;
    314 		}
    315 	}
    316 }