nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: nuclear@0: void init(void); nuclear@0: void expression(void); nuclear@0: void term(void); nuclear@0: void factor(void); nuclear@0: void add(void); nuclear@0: void sub(void); nuclear@0: void mul(void); nuclear@0: void divide(void); nuclear@0: void get_char(void); nuclear@0: void match(char c); nuclear@0: char get_name(void); nuclear@0: char get_num(void); nuclear@0: void stop(const char *s, ...); nuclear@0: void expected(const char *s); nuclear@0: void emit(const char *fmt, ...); nuclear@0: void vemit(const char *fmt, va_list ap); nuclear@0: void emitln(const char *fmt, ...); nuclear@0: int is_addsub(char c); nuclear@0: nuclear@0: FILE *infile, *outfile; nuclear@0: char look; nuclear@0: nuclear@0: static const char *prologue = nuclear@0: "\t.globl _start\n" nuclear@0: "_start:\n" nuclear@0: "\tcall main\n" nuclear@0: "\tmov %eax, %ebx\n" nuclear@0: "\tmov $1, %eax\n" nuclear@0: "\tint $0x80\n" nuclear@0: "main:\n" nuclear@0: "\t# ---- START ----\n"; nuclear@0: nuclear@0: static const char *epilogue = "\t# ---- END ----\n\tret\n"; nuclear@0: nuclear@0: int main(void) nuclear@0: { nuclear@0: infile = stdin; nuclear@0: outfile = stdout; nuclear@0: nuclear@0: init(); nuclear@0: /* output prologue */ nuclear@0: fputs(prologue, outfile); nuclear@0: nuclear@0: expression(); nuclear@0: nuclear@0: /* output epilogue */ nuclear@0: fputs(epilogue, outfile); nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: void init(void) nuclear@0: { nuclear@0: get_char(); nuclear@0: } nuclear@0: nuclear@0: void expression(void) nuclear@0: { nuclear@0: if(is_addsub(look)) { nuclear@0: emitln("xor %%eax, %%eax"); nuclear@0: } else { nuclear@0: term(); nuclear@0: } nuclear@0: nuclear@0: while(is_addsub(look)) { nuclear@0: emitln("push %%eax"); nuclear@0: switch(look) { nuclear@0: case '+': nuclear@0: add(); nuclear@0: break; nuclear@0: case '-': nuclear@0: sub(); nuclear@0: break; nuclear@0: default: nuclear@0: expected("addop"); nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void term(void) nuclear@0: { nuclear@0: factor(); nuclear@0: while(look == '*' || look == '/') { nuclear@0: emitln("push %%eax"); nuclear@0: switch(look) { nuclear@0: case '*': nuclear@0: mul(); nuclear@0: break; nuclear@0: case '/': nuclear@0: divide(); nuclear@0: break; nuclear@0: default: nuclear@0: expected("mulop"); nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void factor(void) nuclear@0: { nuclear@0: if(look == '(') { nuclear@0: match('('); nuclear@0: expression(); nuclear@0: match(')'); nuclear@0: } else { nuclear@0: emitln("mov $%c, %%eax", get_num()); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void add(void) nuclear@0: { nuclear@0: match('+'); nuclear@0: term(); nuclear@0: emitln("pop %%ebx"); nuclear@0: emitln("add %%ebx, %%eax"); nuclear@0: } nuclear@0: nuclear@0: void sub(void) nuclear@0: { nuclear@0: match('-'); nuclear@0: term(); nuclear@0: emitln("pop %%ebx"); nuclear@0: emitln("sub %%ebx, %%eax"); nuclear@0: emitln("neg %%eax"); nuclear@0: } nuclear@0: nuclear@0: void mul(void) nuclear@0: { nuclear@0: match('*'); nuclear@0: factor(); nuclear@0: emitln("pop %%ebx"); nuclear@0: emitln("imul %%ebx"); nuclear@0: } nuclear@0: nuclear@0: void divide(void) nuclear@0: { nuclear@0: match('/'); nuclear@0: factor(); nuclear@0: emitln("mov %%eax, %%ebx"); nuclear@0: emitln("pop %%eax"); nuclear@0: emitln("idiv %%ebx"); nuclear@0: } nuclear@0: nuclear@0: void get_char(void) nuclear@0: { nuclear@0: look = fgetc(infile); nuclear@0: } nuclear@0: nuclear@0: void match(char c) nuclear@0: { nuclear@0: if(look == c) { nuclear@0: get_char(); nuclear@0: } else { nuclear@0: char s[2] = {0, 0}; nuclear@0: s[0] = c; nuclear@0: expected(s); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: char get_name(void) nuclear@0: { nuclear@0: char res; nuclear@0: if(!isalpha(look)) { nuclear@0: expected("name"); nuclear@0: } nuclear@0: res = toupper(look); nuclear@0: get_char(); nuclear@0: return res; nuclear@0: } nuclear@0: nuclear@0: char get_num(void) nuclear@0: { nuclear@0: char res; nuclear@0: if(!isdigit(look)) { nuclear@0: expected("integer"); nuclear@0: } nuclear@0: res = look; nuclear@0: get_char(); nuclear@0: return res; nuclear@0: } nuclear@0: nuclear@0: void stop(const char *s, ...) nuclear@0: { nuclear@0: va_list ap; nuclear@0: nuclear@0: fprintf(stderr, "error: "); nuclear@0: va_start(ap, s); nuclear@0: vfprintf(stderr, s, ap); nuclear@0: va_end(ap); nuclear@0: fputc('\n', stderr); nuclear@0: nuclear@0: abort(); nuclear@0: } nuclear@0: nuclear@0: void expected(const char *s) nuclear@0: { nuclear@0: stop("%s expected", s); nuclear@0: } nuclear@0: nuclear@0: void emit(const char *fmt, ...) nuclear@0: { nuclear@0: va_list ap; nuclear@0: va_start(ap, fmt); nuclear@0: vemit(fmt, ap); nuclear@0: va_end(ap); nuclear@0: } nuclear@0: nuclear@0: void vemit(const char *fmt, va_list ap) nuclear@0: { nuclear@0: fputc('\t', outfile); nuclear@0: vfprintf(outfile, fmt, ap); nuclear@0: } nuclear@0: nuclear@0: void emitln(const char *fmt, ...) nuclear@0: { nuclear@0: va_list ap; nuclear@0: va_start(ap, fmt); nuclear@0: vemit(fmt, ap); nuclear@0: va_end(ap); nuclear@0: fputc('\n', outfile); nuclear@0: } nuclear@0: nuclear@0: nuclear@0: int is_addsub(char c) nuclear@0: { nuclear@0: return c == '+' || c == '-'; nuclear@0: }