comptut

view src/main.c @ 4:ae1c30fa39f3

working on the control structures of tutorial5
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 16 Mar 2015 00:13:54 +0200
parents f167a743f348
children bebbe71ba949
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <ctype.h>
4 #include <stdarg.h>
6 enum { SYM_VAR, SYM_FUNC };
8 struct symbol {
9 int type;
10 char name;
11 struct symbol *next;
12 };
14 void init(void);
15 void program(void);
16 void block(void);
17 void doif(void);
18 void dowhile(void);
19 void condition(void);
20 void expression(void);
21 void assignment(void);
22 void term(void);
23 void factor(void);
24 void ident(void);
25 void add(void);
26 void sub(void);
27 void mul(void);
28 void divide(void);
29 void get_char(void);
30 void match(char c);
31 char get_name(void);
32 char get_num(void);
33 void skip_white(void);
34 void stop(const char *s, ...);
35 void expected(const char *s);
36 void emit(const char *fmt, ...);
37 void vemit(const char *fmt, va_list ap);
38 void emitln(const char *fmt, ...);
39 int is_addsub(char c);
40 int add_symbol(char c, int type);
41 int newlabel(void);
42 const char *labelstr(int lb);
43 void postlabel(int lb);
44 void other(void);
46 FILE *infile, *outfile;
47 char look;
49 struct symbol *symlist;
51 static const char *prologue =
52 "\t.globl _start\n"
53 "_start:\n"
54 "\tcall main\n"
55 "\tmov %eax, %ebx\n"
56 "\tmov $1, %eax\n"
57 "\tint $0x80\n"
58 "main:\n"
59 "\t# ---- START ----\n";
61 static const char *epilogue = "\t# ---- END ----\n\tret\n";
63 int main(void)
64 {
65 infile = stdin;
66 outfile = stdout;
68 init();
69 /* output prologue */
70 fputs(prologue, outfile);
72 program();
74 /* output epilogue */
75 fputs(epilogue, outfile);
76 /* write all variable declarations */
77 fprintf(outfile, "\t.data\n");
78 while(symlist) {
79 struct symbol *sym = symlist;
80 symlist = symlist->next;
81 if(sym->type == SYM_VAR) {
82 fprintf(outfile, "%c:\t.long 0\n", sym->name);
83 }
84 free(sym);
85 }
86 return 0;
87 }
89 void init(void)
90 {
91 get_char();
92 skip_white();
93 }
95 void program(void)
96 {
97 block();
98 if(look != 'e') {
99 expected("End");
100 }
101 emitln("# END");
102 }
104 void other(void)
105 {
106 emitln("%c", get_name());
107 }
109 void block(void)
110 {
111 while(look != 'e' && look != 'l') {
112 switch(look) {
113 case 'i':
114 doif();
115 break;
117 case 'w':
118 dowhile();
119 break;
121 default:
122 other();
123 break;
124 }
125 }
126 }
128 void doif(void)
129 {
130 int lb1, lb2;
132 match('i');
133 condition();
135 lb1 = newlabel();
136 lb2 = lb1;
138 emitln("jz %s", labelstr(lb1));
139 block();
141 if(look == 'l') {
142 match('l');
143 lb2 = newlabel();
144 emitln("jmp %s", labelstr(lb2));
145 postlabel(lb1);
146 block();
147 }
148 match('e');
149 postlabel(lb2);
150 }
152 void dowhile(void)
153 {
154 int lbtop, lbend;
156 match('w');
157 lbtop = newlabel();
158 lbend = newlabel();
159 postlabel(lbtop);
160 condition();
161 emitln("jz %s", labelstr(lbend));
162 block();
163 match('e');
164 emitln("jmp %s", labelstr(lbtop));
165 postlabel(lbend);
166 }
168 void condition(void)
169 {
170 emitln("<condition>");
171 }
173 void expression(void)
174 {
175 if(is_addsub(look)) {
176 emitln("xor %%eax, %%eax");
177 } else {
178 term();
179 }
181 while(is_addsub(look)) {
182 emitln("push %%eax");
183 switch(look) {
184 case '+':
185 add();
186 break;
187 case '-':
188 sub();
189 break;
190 }
191 }
192 }
194 void assignment(void)
195 {
196 char name = get_name();
197 match('=');
199 if(add_symbol(name, SYM_VAR) == -1) {
200 stop("variable name '%c' previously defined as another type of symbol\n", name);
201 }
203 expression();
204 emitln("mov %%eax, (%c)", name);
205 }
207 void term(void)
208 {
209 factor();
210 while(look == '*' || look == '/') {
211 emitln("push %%eax");
212 switch(look) {
213 case '*':
214 mul();
215 break;
216 case '/':
217 divide();
218 break;
219 }
220 }
221 }
223 void factor(void)
224 {
225 if(look == '(') {
226 match('(');
227 expression();
228 match(')');
229 } else if(isalpha(look)) {
230 ident();
231 } else {
232 emitln("mov $%c, %%eax", get_num());
233 }
234 }
236 void ident(void)
237 {
238 char name = get_name();
239 if(look == '(') {
240 /* function call */
241 match('(');
242 match(')');
244 if(add_symbol(name, SYM_FUNC) == -1) {
245 stop("function name '%c' previously defined as another type of symbol\n", name);
246 }
247 emitln("call %c", name);
248 } else {
249 /* variable */
250 if(add_symbol(name, SYM_VAR) == -1) {
251 stop("variable name '%c' previously defined as another type of symbol\n", name);
252 }
253 emitln("mov (%c), %%eax", name);
254 }
255 }
257 void add(void)
258 {
259 match('+');
260 term();
261 emitln("pop %%ebx");
262 emitln("add %%ebx, %%eax");
263 }
265 void sub(void)
266 {
267 match('-');
268 term();
269 emitln("pop %%ebx");
270 emitln("sub %%ebx, %%eax");
271 emitln("neg %%eax");
272 }
274 void mul(void)
275 {
276 match('*');
277 factor();
278 emitln("pop %%ebx");
279 emitln("imul %%ebx");
280 }
282 void divide(void)
283 {
284 match('/');
285 factor();
286 emitln("mov %%eax, %%ebx");
287 emitln("pop %%eax");
288 emitln("idiv %%ebx");
289 }
291 void get_char(void)
292 {
293 look = fgetc(infile);
294 }
296 void match(char c)
297 {
298 if(look == c) {
299 get_char();
300 skip_white();
301 } else {
302 char s[2] = {0, 0};
303 s[0] = c;
304 expected(s);
305 }
306 }
308 char get_name(void)
309 {
310 char res;
311 if(!isalpha(look)) {
312 expected("name");
313 }
314 res = toupper(look);
315 get_char();
316 skip_white();
317 return res;
318 }
320 char get_num(void)
321 {
322 char res;
323 if(!isdigit(look)) {
324 expected("integer");
325 }
326 res = look;
327 get_char();
328 skip_white();
329 return res;
330 }
332 void skip_white(void)
333 {
334 while(isblank(look)) {
335 get_char();
336 }
337 }
339 void stop(const char *s, ...)
340 {
341 va_list ap;
343 fprintf(stderr, "error: ");
344 va_start(ap, s);
345 vfprintf(stderr, s, ap);
346 va_end(ap);
347 fputc('\n', stderr);
349 abort();
350 }
352 void expected(const char *s)
353 {
354 stop("%s expected", s);
355 }
357 void emit(const char *fmt, ...)
358 {
359 va_list ap;
360 va_start(ap, fmt);
361 vemit(fmt, ap);
362 va_end(ap);
363 }
365 void vemit(const char *fmt, va_list ap)
366 {
367 fputc('\t', outfile);
368 vfprintf(outfile, fmt, ap);
369 }
371 void emitln(const char *fmt, ...)
372 {
373 va_list ap;
374 va_start(ap, fmt);
375 vemit(fmt, ap);
376 va_end(ap);
377 fputc('\n', outfile);
378 }
381 int is_addsub(char c)
382 {
383 return c == '+' || c == '-';
384 }
386 int add_symbol(char c, int type)
387 {
388 struct symbol *sym = symlist;
389 while(sym) {
390 if(sym->name == c) {
391 /* we already have it */
392 return sym->type == type ? 0 : -1;
393 }
394 sym = sym->next;
395 }
397 if(!(sym = malloc(sizeof *sym))) {
398 perror("ICE: failed to allocate memory");
399 abort();
400 }
401 sym->name = c;
402 sym->type = type;
403 sym->next = symlist;
404 symlist = sym;
405 return 0;
406 }
408 int newlabel(void)
409 {
410 static int n;
411 return n++;
412 }
414 const char *labelstr(int lb)
415 {
416 static char buf[16];
417 sprintf(buf, "L%02d", lb);
418 return buf;
419 }
421 void postlabel(int lb)
422 {
423 fprintf(outfile, "%s:\n", labelstr(lb));
424 }