scc

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

expr.c (3858B)


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