comptut

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