comptut

view src/main.c @ 0:10f07b308aab

tutor2.txt completed
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 15 Mar 2015 05:47:44 +0200
parents
children f167a743f348
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <ctype.h>
4 #include <stdarg.h>
6 void init(void);
7 void expression(void);
8 void term(void);
9 void factor(void);
10 void add(void);
11 void sub(void);
12 void mul(void);
13 void divide(void);
14 void get_char(void);
15 void match(char c);
16 char get_name(void);
17 char get_num(void);
18 void stop(const char *s, ...);
19 void expected(const char *s);
20 void emit(const char *fmt, ...);
21 void vemit(const char *fmt, va_list ap);
22 void emitln(const char *fmt, ...);
23 int is_addsub(char c);
25 FILE *infile, *outfile;
26 char look;
28 static const char *prologue =
29 "\t.globl _start\n"
30 "_start:\n"
31 "\tcall main\n"
32 "\tmov %eax, %ebx\n"
33 "\tmov $1, %eax\n"
34 "\tint $0x80\n"
35 "main:\n"
36 "\t# ---- START ----\n";
38 static const char *epilogue = "\t# ---- END ----\n\tret\n";
40 int main(void)
41 {
42 infile = stdin;
43 outfile = stdout;
45 init();
46 /* output prologue */
47 fputs(prologue, outfile);
49 expression();
51 /* output epilogue */
52 fputs(epilogue, outfile);
53 return 0;
54 }
56 void init(void)
57 {
58 get_char();
59 }
61 void expression(void)
62 {
63 if(is_addsub(look)) {
64 emitln("xor %%eax, %%eax");
65 } else {
66 term();
67 }
69 while(is_addsub(look)) {
70 emitln("push %%eax");
71 switch(look) {
72 case '+':
73 add();
74 break;
75 case '-':
76 sub();
77 break;
78 default:
79 expected("addop");
80 }
81 }
82 }
84 void term(void)
85 {
86 factor();
87 while(look == '*' || look == '/') {
88 emitln("push %%eax");
89 switch(look) {
90 case '*':
91 mul();
92 break;
93 case '/':
94 divide();
95 break;
96 default:
97 expected("mulop");
98 }
99 }
100 }
102 void factor(void)
103 {
104 if(look == '(') {
105 match('(');
106 expression();
107 match(')');
108 } else {
109 emitln("mov $%c, %%eax", get_num());
110 }
111 }
113 void add(void)
114 {
115 match('+');
116 term();
117 emitln("pop %%ebx");
118 emitln("add %%ebx, %%eax");
119 }
121 void sub(void)
122 {
123 match('-');
124 term();
125 emitln("pop %%ebx");
126 emitln("sub %%ebx, %%eax");
127 emitln("neg %%eax");
128 }
130 void mul(void)
131 {
132 match('*');
133 factor();
134 emitln("pop %%ebx");
135 emitln("imul %%ebx");
136 }
138 void divide(void)
139 {
140 match('/');
141 factor();
142 emitln("mov %%eax, %%ebx");
143 emitln("pop %%eax");
144 emitln("idiv %%ebx");
145 }
147 void get_char(void)
148 {
149 look = fgetc(infile);
150 }
152 void match(char c)
153 {
154 if(look == c) {
155 get_char();
156 } else {
157 char s[2] = {0, 0};
158 s[0] = c;
159 expected(s);
160 }
161 }
163 char get_name(void)
164 {
165 char res;
166 if(!isalpha(look)) {
167 expected("name");
168 }
169 res = toupper(look);
170 get_char();
171 return res;
172 }
174 char get_num(void)
175 {
176 char res;
177 if(!isdigit(look)) {
178 expected("integer");
179 }
180 res = look;
181 get_char();
182 return res;
183 }
185 void stop(const char *s, ...)
186 {
187 va_list ap;
189 fprintf(stderr, "error: ");
190 va_start(ap, s);
191 vfprintf(stderr, s, ap);
192 va_end(ap);
193 fputc('\n', stderr);
195 abort();
196 }
198 void expected(const char *s)
199 {
200 stop("%s expected", s);
201 }
203 void emit(const char *fmt, ...)
204 {
205 va_list ap;
206 va_start(ap, fmt);
207 vemit(fmt, ap);
208 va_end(ap);
209 }
211 void vemit(const char *fmt, va_list ap)
212 {
213 fputc('\t', outfile);
214 vfprintf(outfile, fmt, ap);
215 }
217 void emitln(const char *fmt, ...)
218 {
219 va_list ap;
220 va_start(ap, fmt);
221 vemit(fmt, ap);
222 va_end(ap);
223 fputc('\n', outfile);
224 }
227 int is_addsub(char c)
228 {
229 return c == '+' || c == '-';
230 }