/*
 * esa2.c
 * Expression reader.
 */
#include <stdio.h>
#include "esa.h"

/*
 * Read in an expression.
 * The type is always absolute.
 * Expressions get interpreted from
 * left to right.
 * No priority.
 * Parentheses may be used to force
 * the order of evaluation.
 */
expr()
{
	register int c;
	int l, r;

	if(!term(&l))
		return(0);
	while(validop(c=getnb())) {
		if(!term(&r)) {
			err('e');
			return(l);
		}
		switch(c) {

		case '+':
			l += r;
			break;

		case '-':
			l -= r;
			break;

		case '*':
			l *= r;
			break;

		case '%':
			l /= r;

		case '&':
			l &= r;
			break;

		case '|':
			l |= r;
		}
	}
	putback(c);
	return(l);
}

/*
 * Test if a character is a valid arithmetic
 * operator.
 * True return if it is.
 */
validop(c)
{
	switch(c) {

	case '+':
	case '-':
	case '*':
	case '%':
	case '&':
	case '|':
		return(1);

	default:
		return(0);
	}
}

/*
 * Get a term.
 * Store it back through the supplied pointer.
 * If no valid term put any characters you read
 * back.
 * True return if a term was obtained.
 */
term(vp)
int *vp;
{
	register struct sym *sp;
	register int c;
	char id[NCPS];

	if((c=getnb())>='0' && c<='9') {
		*vp = getnum(c);
		return(1);
	} else if(alpha(c)) {
		getid(c, id);
		sp = lookup(id, ust);
		if(sp->s_type == S_UND)
			err('u');
		*vp = sp->s_value;
		return(1);
	} else if(c=='-' || c=='!') {
		if(!term(vp)) {
			err('e');
			return(0);
		} else if(c == '-')
			*vp = -*vp;
		else
			*vp = ~*vp;
	} else if(c == '(') {
		*vp = expr();
		if(getnb() != ')')
			err('(');
		return(1);
	} else if(c == '\'') {
		*vp = getmap();
		if(getnb() != '\'')
			err('\'');
		return(1);
	} else {
		putback(c);
		return(0);
	}
}
