/*
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 */