expr.c - scc - simple c99 compiler
(HTM) git clone git://git.simple-cc.org/scc
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Submodules
(DIR) README
(DIR) 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 }