#include <stdlib.h>
#include "basic.h"
void level2(int*), level3(int*), level4(int*), level5(int*), level6(int*), primitive(int*);
void unary(char, int*), arith(char, int*, int*);
/* Entry point into parser. */
void get_exp(int *result)
{
get_token();
if(!*token) {
serror(2);
return;
}
level2(result);
putback(); /* return last token read to input stream */
}
/* Add or subtract two terms. */
void level2(int *result)
{
register char op;
int hold;
level3(result);
while((op = *token) == '+' || op == '-') {
get_token();
level3(&hold);
arith(op, result, &hold);
}
}
/* Multiply or divide two factors. */
void level3(int *result)
{
register char op;
int hold;
level4(result);
while((op = *token) == '*' || op == '/' || op == '%') {
get_token();
level4(&hold);
arith(op, result, &hold);
}
}
/* Process integer exponent. */
void level4(int *result)
{
int hold;
level5(result);
if(*token== '^') {
get_token();
level4(&hold);
arith('^', result, &hold);
}
}
/* Is a unary + or -. */
void level5(int *result)
{
register char op;
op = 0;
if((token_type==DELIMITER) && (*token=='+' || *token=='-')) {
op = *token;
get_token();
}
level6(result);
if(op)
unary(op, result);
}
/* Process parenthesized expression. */
void level6(int *result)
{
if((*token == '(') && (token_type == DELIMITER)) {
get_token();
level2(result);
if(*token != ')')
serror(1);
get_token();
}
else
primitive(result);
}
/* Find value of number or variable. */
void primitive(int *result)
{
switch(token_type) {
case VARIABLE:
*result = *find_var(token);
get_token();
return;
case NUMBER:
*result = atoi(token);
get_token();
return;
case COMMAND:
switch(tok) {
case RND:
*result = rand();
get_token();
return;
}
default:
serror(0);
}
}
/* Perform the specified arithmetic. */
void arith(char o, int *r, int *h)
{
register int t, ex;
switch(o) {
case '-':
*r = *r-*h;
break;
case '+':
*r = *r+*h;
break;
case '*':
*r = *r * *h;
break;
case '/':
*r = (*r)/(*h);
break;
case '%':
t = (*r)/(*h);
*r = *r-(t*(*h));
break;
case '^':
ex = *r;
if(*h==0) {
*r = 1;
break;
}
for(t=*h-1; t>0; --t) *r = (*r) * ex;
break;
}
}
/* Reverse the sign. */
void unary(char o, int *r)
{
if(o=='-') *r = -(*r);
}