scc

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

expr.c (4020B)


      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 	unsigned long long 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 
    136 	np = node(op, l, r);
    137 	np->addr = addr;
    138 
    139 	return np;
    140 }
    141 
    142 static Node *
    143 unaryop(int op, Node *np)
    144 {
    145 	unsigned long long val;
    146 
    147 	if (np->addr != ANUMBER)
    148 		error("invalid argument for unary operator");
    149 	if (np->op != NUMBER) {
    150 		np = node(op, np, NULL);
    151 		np->addr = ANUMBER;
    152 		return np;
    153 	}
    154 
    155 	val = np->sym->value;
    156 	switch (op) {
    157 	case '!':
    158 		val = !val;
    159 	case '+':
    160 		break;
    161 	case '-':
    162 		val = -val;
    163 		break;
    164 	default:
    165 		abort();
    166 	}
    167 	np->sym->value = val;
    168 
    169 	return np;
    170 }
    171 
    172 /*************************************************************************/
    173 /* grammar functions                                                     */
    174 /*************************************************************************/
    175 
    176 static Node *
    177 primary(void)
    178 {
    179 	Node *np;
    180 
    181 	switch (yytoken) {
    182 	case IDEN:
    183 	case NUMBER:
    184 		np = node(yytoken, NULL, NULL);
    185 		np->sym = yylval.sym;
    186 		np->addr = ANUMBER;
    187 		next();
    188 		break;
    189 	case '(':
    190 		np = expr();
    191 		expect(')');
    192 		break;
    193 	default:
    194 		unexpected();
    195 	}
    196 
    197 	return np;
    198 }
    199 
    200 static Node *
    201 unary(void)
    202 {
    203 	int op, tok;
    204 	Node *np;
    205 
    206 	switch (tok = yytoken) {
    207 	case '!':
    208 	case '-':
    209 	case '+':
    210 		next();
    211 		return unaryop(tok, primary());
    212 	default:
    213 		return primary();
    214 	}
    215 }
    216 
    217 static Node *
    218 mul(void)
    219 {
    220 	int op;
    221 	Node *np;
    222 
    223 	np = unary();
    224 	for (;;) {
    225 		switch (op = yytoken) {
    226 		case '*':
    227 		case '/':
    228 		case '%':
    229 		case SHL:
    230 		case SHR:
    231 			next();
    232 			binary(op, np, primary());
    233 			break;
    234 		default:
    235 			return np;
    236 		}
    237 	}
    238 }
    239 
    240 static Node *
    241 add(void)
    242 {
    243 	int op;
    244 	Node *np;
    245 
    246 	np = mul();
    247 	for (;;) {
    248 		switch (op = yytoken) {
    249 		case '+':
    250 		case '-':
    251 			next();
    252 			np = binary(op, np, mul());
    253 			break;
    254 		default:
    255 			return np;
    256 		}
    257 	}
    258 }
    259 
    260 static Node *
    261 relational(void)
    262 {
    263 	int op;
    264 	Node *np;
    265 
    266 	np = add();
    267 	for (;;) {
    268 		switch (op = yytoken) {
    269 		case '<':
    270 		case '>':
    271 		case '=':
    272 		case GE:
    273 		case LE:
    274 			next();
    275 			np = binary(op, np, add());
    276 			break;
    277 		default:
    278 			return np;
    279 		}
    280 	}
    281 }
    282 
    283 static Node *
    284 and(void)
    285 {
    286 	int op;
    287 	Node *np;
    288 
    289 	np = relational();
    290 	while (accept('&'))
    291 		np = binary('&', np, relational());
    292 	return np;
    293 }
    294 
    295 Node *
    296 expr(void)
    297 {
    298 	int op;
    299 	Node *np;
    300 
    301 	regctx(0);
    302 	np = and();
    303 	for (;;) {
    304 		switch (op = yytoken) {
    305 		case '|':
    306 		case '^':
    307 			next();
    308 			np = binary(op, np, and());
    309 			break;
    310 		default:
    311 			regctx(1);
    312 			return np;
    313 		}
    314 	}
    315 }