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