/*
 * parser2.c    Abby Ge 11/3/1999
 * 	Parser that interpretates addition and multiplication with decimal
 *	numbers 
 */

#include <stdio.h>

char current_char;

int nextchar(void);
float expression(void);
float ebar(void);
float term(void);
float tbar(void);
float factor(void);
float variable(void);

int nextchar(void) {
	while (((current_char = getchar()) != EOF) && (current_char == ' '))
		;
  	return current_char;
}

void error(char *pname) {
  	int c;
  	fprintf(stderr, "Error in function ");
  	fprintf(stderr, pname);
  	fprintf(stderr, ": \n  current_char = ");
  	putc(current_char, stderr);
  	fprintf(stderr, "\n  string remaining = ");
  	while (((c = getchar()) != EOF) && (c != '\n'))
    		putc(c, stderr);
  	fprintf(stderr, "\n\n");
}

float expression(void) {
  	float termvalue, ebarvalue;
  	switch (current_char) {
  	case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
	case '.':
  	case '(':
    		termvalue = term();
		ebarvalue = ebar();
		return (termvalue + ebarvalue);
  	default:
    		error("expression");
  	}
}

float ebar(void) {
  	switch (current_char) {
  	case '+':
    		nextchar();
    		return expression();
  	case ')':
  	case '\n':
    		return 0;
  	default:
    		error("ebar");
  	}
}

float term(void) {
  	float factorvalue, tbarvalue;
  	switch (current_char) {
	case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
	case '.':
  	case '(':
		factorvalue=factor();
		tbarvalue = tbar();
    		return (factorvalue * tbarvalue);
  	default:
    		error("term");
  	}	
}

float tbar(void) {
  	float fatorvalue, tbarvalue;
  	switch (current_char) {
  	case '*':
    		nextchar();
    		return term();
  	case '+':
  	case ')':
  	case '\n':
    		return 1;
  	default:
    		error("tbar");
  	}
}

float factor(void) {
  	float expressionvalue;
  	switch (current_char) {
	case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
	case '.':
    		return variable();
 	case '(':
    		nextchar();
    		expressionvalue = expression();
    		if (current_char == ')') {
      		nextchar();
      		return expressionvalue;
    	} else {
      		error("factor");
    	  }
    	break;
  	default:
    	error("factor");
  	}
}

float variable(void) {
	int counter=0;
	float x=0;

	int number(void);
	int u(void);
	int sign(void);
	int z(void);
	int zbar(void); 
	int r(void);
	int digit(void);

	int number(void) {
        	int uvalue;
        	switch (current_char) {
        	case '0':
        	case '1':
        	case '2':
        	case '3':   
        	case '4':
        	case '5':
        	case '6':
        	case '7':
        	case '8': 
        	case '9':  
                	uvalue=u();
                	return(uvalue);
        	case '.':
                	uvalue=u();
                	return (uvalue);
		case '*':
		case '(':
		case ')':
		case '\n':
		case '+':
			return;        	
		default: 
                error("number");
        	}
	}

	int u(void){
        	int i,digitvalue,rvalue,zvalue;
        	switch (current_char) {
        	case '0':
        	case '1':
        	case '2':
        	case '3':
       	 	case '4':
        	case '5':
        	case '6':
        	case '7':
        	case '8':
        	case '9':
                	digitvalue=digit();
                	x=x*10+digitvalue;
                	nextchar();
			rvalue=r();
                	if (rvalue==-1) return;
                	return (x);
        	case '.':
                	nextchar();
                	zvalue=z();
                	return(x);
        	default:
                	error ("u");
        	}
	}

	int z(void){
        	int i;
        	float digitvalue,zbarvalue;
        	switch (current_char) {
        	case '0':
        	case '1':
        	case '2':
        	case '3':
        	case '4':
        	case '5':
        	case '6':
        	case '7':
        	case '8':
        	case '9':
        	        digitvalue=digit();
        	        counter++;
        	        i=counter;
        	        while (i>0){
        	                digitvalue/=10;
        	                i--;
        	        }
        	        x=x+digitvalue;
        	        nextchar();
        	        zbarvalue=zbar();
        	        if (zbarvalue==-1)      return;
        	        return(x);
        	default:
        	        error("z");
        	}
	}	
	
	int zbar(void){  
	        float zvalue;
	        switch (current_char) {
	        case '0':
	        case '1':
	        case '2':
	        case '3':
	        case '4':
	        case '5':
	        case '6':
	        case '7':
	        case '8':
	        case '9':
	                zvalue=z();
	                return(zvalue);  
	        case '+':
		case '*':
		case '(':
		case ')':
		case '\n':
	                return(-1);
	        default:
	                error("zbar");
	        }
	}

	int r(void){
	        int i,digitvalue,rvalue,zbarvalue;
        	switch (current_char) {
        	case '0':
        	case '1':
	        case '2':
	        case '3':
	        case '4':
	        case '5':
	        case '6':
	        case '7':
	        case '8':
	        case '9':
	                digitvalue=digit();
	                x=x*10+digitvalue;
	                nextchar();
	                rvalue=r();
	                if (rvalue==-1) return;
	                return(x);
	        case '.':
	                nextchar();
	                zbarvalue=zbar();
	                return(zbarvalue);
	        case '+':
		case '*':
		case '(':
		case ')':
		case '\n':
	                return(-1);
	        default:
	                error ("r");
	        }
	}

	int digit(void){ 
	        switch (current_char) {
	        case '0':
	                return (0);
	        case '1':
	                return (1);
	        case '2':
	                return (2);
	        case '3':
	                return (3);
	        case '4':
	                return (4);
	        case '5':
	                return (5);
	        case '6':
	                return (6);
	        case '7':
	                return (7);
	        case '8': 
	                return (8);
	        case '9':
	                return (9); 
	        default:
	                error ("digit");
	        }
	}

	number();
	return (x);
}

int main(void) {
  	do {
    		printf("> ");
    		if (nextchar() != EOF)	printf("%f\n\n", expression());
  	} while (current_char != EOF);
  	return 0;	
}

