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 +}