comptut

changeset 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 db0630e6a97b
children ae1c30fa39f3
files src/main.c
diffstat 1 files changed, 97 insertions(+), 5 deletions(-) [+]
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 +}