/* Very Simple Compiler (Parser part, Tree Genertor) $Id: s-tree-compile.c,v 2.0 1996/11/18 19:55:50 kono Exp kono $ */ #include "s-compile.h" char *ptr,*last_ptr,*before; int value,lvalue; int last_token; int variable[48]; typedef struct node { struct node *left; struct node *right; int type; int value; } node; void error(); node *expr(); node *aexpr(); node *mexpr(); node *term(); int token(); node *new_node(); void print_node(); node * new_node(type,value,left,right) int type; int value; node *left; node *right; { node *d; if ((left && left->type =='0') && (right && right->type =='0')) { switch(type) { case '>': right->value = (left->value > right->value); free(left); return right; break; case '+': right->value = left->value + right->value; free(left); return right; break; case '-': right->value = left->value - right->value; free(left); return right; break; case '*': right->value = right->value * left->value; free(left); return right; break; case '/': if(right->value==0) { error("zero divide in compile time"); } else { right->value = left->value / right->value; } free(left); return right; } } d = (node *)malloc(sizeof(node)); d->type = type; d->value = value; d->left = left; d->right = right; return d; } void free_node(d) node *d; { if(d->left) { free_node(d->left); } if(d->right) { free_node(d->right); } free(d); } void code_generate(d) node *d; { int assign; switch(d->type) { case '0': emit_value(d->value); return; case 'v': emit_load(d->value); return; case '=': if(!d->left || d->left->type != 'v') { error("Bad assignment"); code_generate(d->right); return; } assign = d->left->value; code_generate(d->right); emit_store(assign); return; case '>': code_generate(d->left); emit_push(); code_generate(d->right); emit_compare(); break; default: /* calculation */ code_generate(d->right); emit_push(); code_generate(d->left); switch(d->type) { case '+': emit_calc(O_ADD); break; case '-': emit_calc(O_SUB_R); break; case '/': emit_calc(O_DIV_R); break; case '*': emit_calc(O_MUL); break; default: error("Internal Error, unknown opecode"); } return; } } int token() { int c,d; last_ptr = ptr; /* for error position */ c= *ptr; if(!c) { last_token = EOF; return last_token; } ptr++; if (c<=' ') { /* comment */ while(*ptr++); ptr--; last_token = EOF; last_ptr = ptr; return last_token; } if('0'<=c && c<='9') { /* Decimal */ d = c-'0'; while(c= *ptr++) { if('0'<=c && c<='9') { d = d*10 + (c - '0'); } else { break; } } c && ptr--; value = d; last_token = '0'; return last_token; } else if ('a'<=c && c<='z') { /* variable */ value = c-'a'; /* return variable reference */ last_token = 'v'; return last_token; } else { last_token = c; return last_token; return c; } } node * expr() { int assign; node *d; d = aexpr(); while(last_token!=EOF) { switch(last_token) { case '>': d = new_node('>',0,d,aexpr()); break; case '=': d = new_node('=',0,d,aexpr()); break; case ')': return d; default: error("Bad expression"); return d; } } return d; } node * aexpr() { node *d; d = mexpr(); while(last_token!=EOF) { switch(last_token) { case '-': d = new_node('-',0,d,mexpr()); break; case '+': d = new_node('+',0,d,mexpr()); break; default: return d; } } return d; } node * mexpr() { node *d; d = term(); while(last_token!=EOF) { switch(last_token) { case '*': d = new_node('*',0,d,term()); break; case '/': d = new_node('/',0,d,term()); break; default: return d; } } return d; } node * term() { node *d; lvalue= -1; token(); if(last_token==EOF) { error("Term expected"); } switch(last_token) { case '0': d = new_node('0',value,NULL,NULL); token(); return d; case 'v': d = new_node('v',value,NULL,NULL); token(); return d; case '(': d = expr(); if(last_token != ')') { error("Unbalanced parenthsis"); } token(); return d; default: token(); error("Unknown term"); return 0; } } int main() { node *d; char buf[BUFSIZ]; emit_intro(); while (fgets(buf,BUFSIZ,stdin)) { ptr = buf; before = buf; printf("%s %s",comments,buf); d = expr(); code_generate(d); free_node(d); emit_print(); emit_comment(); } emit_ending(); return 0; } void error(s) char *s; { fprintf(stderr,"%s on %s\n",s,last_ptr); } /* end */