comptut
diff src/main.c @ 3:f167a743f348
tutor3.txt completed minus the multi-char tokens bit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 15 Mar 2015 13:48:04 +0200 |
parents | 10f07b308aab |
children | ae1c30fa39f3 |
line diff
1.1 --- a/src/main.c Sun Mar 15 05:56:33 2015 +0200 1.2 +++ b/src/main.c Sun Mar 15 13:48:04 2015 +0200 1.3 @@ -3,10 +3,20 @@ 1.4 #include <ctype.h> 1.5 #include <stdarg.h> 1.6 1.7 +enum { SYM_VAR, SYM_FUNC }; 1.8 + 1.9 +struct symbol { 1.10 + int type; 1.11 + char name; 1.12 + struct symbol *next; 1.13 +}; 1.14 + 1.15 void init(void); 1.16 void expression(void); 1.17 +void assignment(void); 1.18 void term(void); 1.19 void factor(void); 1.20 +void ident(); 1.21 void add(void); 1.22 void sub(void); 1.23 void mul(void); 1.24 @@ -15,16 +25,20 @@ 1.25 void match(char c); 1.26 char get_name(void); 1.27 char get_num(void); 1.28 +void skip_white(void); 1.29 void stop(const char *s, ...); 1.30 void expected(const char *s); 1.31 void emit(const char *fmt, ...); 1.32 void vemit(const char *fmt, va_list ap); 1.33 void emitln(const char *fmt, ...); 1.34 int is_addsub(char c); 1.35 +int add_symbol(char c, int type); 1.36 1.37 FILE *infile, *outfile; 1.38 char look; 1.39 1.40 +struct symbol *symlist; 1.41 + 1.42 static const char *prologue = 1.43 "\t.globl _start\n" 1.44 "_start:\n" 1.45 @@ -46,16 +60,30 @@ 1.46 /* output prologue */ 1.47 fputs(prologue, outfile); 1.48 1.49 - expression(); 1.50 + assignment(); 1.51 + if(look != '\n') { 1.52 + expected("newline"); 1.53 + } 1.54 1.55 /* output epilogue */ 1.56 fputs(epilogue, outfile); 1.57 + /* write all variable declarations */ 1.58 + fprintf(outfile, "\t.data\n"); 1.59 + while(symlist) { 1.60 + struct symbol *sym = symlist; 1.61 + symlist = symlist->next; 1.62 + if(sym->type == SYM_VAR) { 1.63 + fprintf(outfile, "%c:\t.long 0\n", sym->name); 1.64 + } 1.65 + free(sym); 1.66 + } 1.67 return 0; 1.68 } 1.69 1.70 void init(void) 1.71 { 1.72 get_char(); 1.73 + skip_white(); 1.74 } 1.75 1.76 void expression(void) 1.77 @@ -75,12 +103,23 @@ 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 assignment(void) 1.88 +{ 1.89 + char name = get_name(); 1.90 + match('='); 1.91 + 1.92 + if(add_symbol(name, SYM_VAR) == -1) { 1.93 + stop("variable name '%c' previously defined as another type of symbol\n", name); 1.94 + } 1.95 + 1.96 + expression(); 1.97 + emitln("mov %%eax, (%c)", name); 1.98 +} 1.99 + 1.100 void term(void) 1.101 { 1.102 factor(); 1.103 @@ -93,8 +132,6 @@ 1.104 case '/': 1.105 divide(); 1.106 break; 1.107 - default: 1.108 - expected("mulop"); 1.109 } 1.110 } 1.111 } 1.112 @@ -105,11 +142,34 @@ 1.113 match('('); 1.114 expression(); 1.115 match(')'); 1.116 + } else if(isalpha(look)) { 1.117 + ident(); 1.118 } else { 1.119 emitln("mov $%c, %%eax", get_num()); 1.120 } 1.121 } 1.122 1.123 +void ident() 1.124 +{ 1.125 + char name = get_name(); 1.126 + if(look == '(') { 1.127 + /* function call */ 1.128 + match('('); 1.129 + match(')'); 1.130 + 1.131 + if(add_symbol(name, SYM_FUNC) == -1) { 1.132 + stop("function name '%c' previously defined as another type of symbol\n", name); 1.133 + } 1.134 + emitln("call %c", name); 1.135 + } else { 1.136 + /* variable */ 1.137 + if(add_symbol(name, SYM_VAR) == -1) { 1.138 + stop("variable name '%c' previously defined as another type of symbol\n", name); 1.139 + } 1.140 + emitln("mov (%c), %%eax", name); 1.141 + } 1.142 +} 1.143 + 1.144 void add(void) 1.145 { 1.146 match('+'); 1.147 @@ -153,6 +213,7 @@ 1.148 { 1.149 if(look == c) { 1.150 get_char(); 1.151 + skip_white(); 1.152 } else { 1.153 char s[2] = {0, 0}; 1.154 s[0] = c; 1.155 @@ -168,6 +229,7 @@ 1.156 } 1.157 res = toupper(look); 1.158 get_char(); 1.159 + skip_white(); 1.160 return res; 1.161 } 1.162 1.163 @@ -179,9 +241,17 @@ 1.164 } 1.165 res = look; 1.166 get_char(); 1.167 + skip_white(); 1.168 return res; 1.169 } 1.170 1.171 +void skip_white(void) 1.172 +{ 1.173 + while(isblank(look)) { 1.174 + get_char(); 1.175 + } 1.176 +} 1.177 + 1.178 void stop(const char *s, ...) 1.179 { 1.180 va_list ap; 1.181 @@ -228,3 +298,25 @@ 1.182 { 1.183 return c == '+' || c == '-'; 1.184 } 1.185 + 1.186 +int add_symbol(char c, int type) 1.187 +{ 1.188 + struct symbol *sym = symlist; 1.189 + while(sym) { 1.190 + if(sym->name == c) { 1.191 + /* we already have it */ 1.192 + return sym->type == type ? 0 : -1; 1.193 + } 1.194 + sym = sym->next; 1.195 + } 1.196 + 1.197 + if(!(sym = malloc(sizeof *sym))) { 1.198 + perror("ICE: failed to allocate memory"); 1.199 + abort(); 1.200 + } 1.201 + sym->name = c; 1.202 + sym->type = type; 1.203 + sym->next = symlist; 1.204 + symlist = sym; 1.205 + return 0; 1.206 +}