/*
Very Simple Calculator
$Id: s-calc.c,v 1.1 1996/09/22 04:43:09 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 */