/* Very Simple Compiler (Parser Part) Parser part $Id: s-compile.c,v 1.1 1996/09/22 11:29:31 kono Exp kono $ */ %{ #include "s-compile.h" void error(char *); void yyerror(char *); 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,*nodeptr; /*typedef node *nodeptr;*/ #define YYSTYPE nodeptr node *new_node(); %} %% top : expr { code_generate($1); free_node($1); emit_print(); emit_comment(); } ; expr : expr '>' aexpr { $$ = new_node('>',0,$1,$3); } | expr '=' aexpr { $$ = new_node('=',0,$1,$3); } | aexpr {$$ = $1; } ; aexpr : aexpr '+' mexpr { $$ = new_node('+',0,$1,$3); } | aexpr '-' mexpr { $$ = new_node('-',0,$1,$3); } | mexpr {$$ = $1; } ; mexpr : mexpr '*' term { $$ = new_node('*',0,$1,$3); } | mexpr '/' term { $$ = new_node('/',0,$1,$3); } | term {$$ = $1; } ; term : '0' { $$ = new_node('0',value,NULL,NULL); } | 'v' { $$ = new_node('v',value,NULL,NULL); } | '(' expr ')' {$$ = $2; } ; %% 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; if(!d) return; /* compiler internal error.. */ 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 yylex() { 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; } } int main() { nodeptr d; char buf[BUFSIZ]; emit_intro(); while (fgets(buf,BUFSIZ,stdin)) { ptr = buf; before = buf; printf("%s %s",comments,buf); yyparse(); } emit_ending(); return 0; } void yyerror(s) char *s; { error(s?s:"error"); } void error(s) char *s; { fprintf(stderr,"%s on %s\n",s,last_ptr); } /* end */