scc

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

expr.c (3814B)


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