comptut
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/main.c Sun Mar 15 05:47:44 2015 +0200 1.3 @@ -0,0 +1,230 @@ 1.4 +#include <stdio.h> 1.5 +#include <stdlib.h> 1.6 +#include <ctype.h> 1.7 +#include <stdarg.h> 1.8 + 1.9 +void init(void); 1.10 +void expression(void); 1.11 +void term(void); 1.12 +void factor(void); 1.13 +void add(void); 1.14 +void sub(void); 1.15 +void mul(void); 1.16 +void divide(void); 1.17 +void get_char(void); 1.18 +void match(char c); 1.19 +char get_name(void); 1.20 +char get_num(void); 1.21 +void stop(const char *s, ...); 1.22 +void expected(const char *s); 1.23 +void emit(const char *fmt, ...); 1.24 +void vemit(const char *fmt, va_list ap); 1.25 +void emitln(const char *fmt, ...); 1.26 +int is_addsub(char c); 1.27 + 1.28 +FILE *infile, *outfile; 1.29 +char look; 1.30 + 1.31 +static const char *prologue = 1.32 + "\t.globl _start\n" 1.33 + "_start:\n" 1.34 + "\tcall main\n" 1.35 + "\tmov %eax, %ebx\n" 1.36 + "\tmov $1, %eax\n" 1.37 + "\tint $0x80\n" 1.38 + "main:\n" 1.39 + "\t# ---- START ----\n"; 1.40 + 1.41 +static const char *epilogue = "\t# ---- END ----\n\tret\n"; 1.42 + 1.43 +int main(void) 1.44 +{ 1.45 + infile = stdin; 1.46 + outfile = stdout; 1.47 + 1.48 + init(); 1.49 + /* output prologue */ 1.50 + fputs(prologue, outfile); 1.51 + 1.52 + expression(); 1.53 + 1.54 + /* output epilogue */ 1.55 + fputs(epilogue, outfile); 1.56 + return 0; 1.57 +} 1.58 + 1.59 +void init(void) 1.60 +{ 1.61 + get_char(); 1.62 +} 1.63 + 1.64 +void expression(void) 1.65 +{ 1.66 + if(is_addsub(look)) { 1.67 + emitln("xor %%eax, %%eax"); 1.68 + } else { 1.69 + term(); 1.70 + } 1.71 + 1.72 + while(is_addsub(look)) { 1.73 + emitln("push %%eax"); 1.74 + switch(look) { 1.75 + case '+': 1.76 + add(); 1.77 + break; 1.78 + case '-': 1.79 + sub(); 1.80 + break; 1.81 + default: 1.82 + expected("addop"); 1.83 + } 1.84 + } 1.85 +} 1.86 + 1.87 +void term(void) 1.88 +{ 1.89 + factor(); 1.90 + while(look == '*' || look == '/') { 1.91 + emitln("push %%eax"); 1.92 + switch(look) { 1.93 + case '*': 1.94 + mul(); 1.95 + break; 1.96 + case '/': 1.97 + divide(); 1.98 + break; 1.99 + default: 1.100 + expected("mulop"); 1.101 + } 1.102 + } 1.103 +} 1.104 + 1.105 +void factor(void) 1.106 +{ 1.107 + if(look == '(') { 1.108 + match('('); 1.109 + expression(); 1.110 + match(')'); 1.111 + } else { 1.112 + emitln("mov $%c, %%eax", get_num()); 1.113 + } 1.114 +} 1.115 + 1.116 +void add(void) 1.117 +{ 1.118 + match('+'); 1.119 + term(); 1.120 + emitln("pop %%ebx"); 1.121 + emitln("add %%ebx, %%eax"); 1.122 +} 1.123 + 1.124 +void sub(void) 1.125 +{ 1.126 + match('-'); 1.127 + term(); 1.128 + emitln("pop %%ebx"); 1.129 + emitln("sub %%ebx, %%eax"); 1.130 + emitln("neg %%eax"); 1.131 +} 1.132 + 1.133 +void mul(void) 1.134 +{ 1.135 + match('*'); 1.136 + factor(); 1.137 + emitln("pop %%ebx"); 1.138 + emitln("imul %%ebx"); 1.139 +} 1.140 + 1.141 +void divide(void) 1.142 +{ 1.143 + match('/'); 1.144 + factor(); 1.145 + emitln("mov %%eax, %%ebx"); 1.146 + emitln("pop %%eax"); 1.147 + emitln("idiv %%ebx"); 1.148 +} 1.149 + 1.150 +void get_char(void) 1.151 +{ 1.152 + look = fgetc(infile); 1.153 +} 1.154 + 1.155 +void match(char c) 1.156 +{ 1.157 + if(look == c) { 1.158 + get_char(); 1.159 + } else { 1.160 + char s[2] = {0, 0}; 1.161 + s[0] = c; 1.162 + expected(s); 1.163 + } 1.164 +} 1.165 + 1.166 +char get_name(void) 1.167 +{ 1.168 + char res; 1.169 + if(!isalpha(look)) { 1.170 + expected("name"); 1.171 + } 1.172 + res = toupper(look); 1.173 + get_char(); 1.174 + return res; 1.175 +} 1.176 + 1.177 +char get_num(void) 1.178 +{ 1.179 + char res; 1.180 + if(!isdigit(look)) { 1.181 + expected("integer"); 1.182 + } 1.183 + res = look; 1.184 + get_char(); 1.185 + return res; 1.186 +} 1.187 + 1.188 +void stop(const char *s, ...) 1.189 +{ 1.190 + va_list ap; 1.191 + 1.192 + fprintf(stderr, "error: "); 1.193 + va_start(ap, s); 1.194 + vfprintf(stderr, s, ap); 1.195 + va_end(ap); 1.196 + fputc('\n', stderr); 1.197 + 1.198 + abort(); 1.199 +} 1.200 + 1.201 +void expected(const char *s) 1.202 +{ 1.203 + stop("%s expected", s); 1.204 +} 1.205 + 1.206 +void emit(const char *fmt, ...) 1.207 +{ 1.208 + va_list ap; 1.209 + va_start(ap, fmt); 1.210 + vemit(fmt, ap); 1.211 + va_end(ap); 1.212 +} 1.213 + 1.214 +void vemit(const char *fmt, va_list ap) 1.215 +{ 1.216 + fputc('\t', outfile); 1.217 + vfprintf(outfile, fmt, ap); 1.218 +} 1.219 + 1.220 +void emitln(const char *fmt, ...) 1.221 +{ 1.222 + va_list ap; 1.223 + va_start(ap, fmt); 1.224 + vemit(fmt, ap); 1.225 + va_end(ap); 1.226 + fputc('\n', outfile); 1.227 +} 1.228 + 1.229 + 1.230 +int is_addsub(char c) 1.231 +{ 1.232 + return c == '+' || c == '-'; 1.233 +}