#include <stdio.h>
#include <setjmp.h>
#include "expr.h"

/* Ejemplo de Descenso Recursivo simple: evaluar una expresion entera constante
 * con notacion de infijo normal y con precedencia habitual: * y / sobre + y -
 * No acepta ni comentarios ni signos en los operandos
 * Gramatica aceptada (desambiguada y con recursion izq eliminada):
 * I -> E;
 * E  -> TE'
 * E' -> +TE' | -TE' | (vacio) 
 * T  -> FT'
 * T' -> *FT' | /FT' | (vacio) 
 * F  -> cte | (E)
 *
 * OJO: Como agregar asignacion a la gramatica:
 * E -> id = E, resulta complejo para descenso recursivo
 */

extern char *yytext;

jmp_buf syn_error;

int NextToken;
char *TokName;

GetNextToken(){
    NextToken = yylex();
    TokName = yytext;
}

main() {
    int res;

    for(;;) {
	/* Buena idea usar longjmp para errores de parsing */
	if( setjmp(syn_error) != 0 )
            fprintf(stderr, "Error de sintaxis\n");

	printf("> "); fflush(stdout);
        GetNextToken();
	if(NextToken == EOF) break;
	res = Expr();
	if(NextToken == SCOLON)
            printf("%d\n", res);
	else
	    fprintf(stderr, "Expresion invalida: no encuentro ; tengo: %s\n", 
TokName);
    }
}

Expr() {
    int res, op;

    res = Term();
    while(NextToken==ADD || NextToken==SUB){
 	op = NextToken;
	GetNextToken();
	res = (op == ADD) ? res + Term() : res - Term();
    }
    return res;
}

Term()
{
    int res, op;

    res = Factor();
    while(NextToken==MUL || NextToken==DIV) {
 	op = NextToken;
	GetNextToken();
	res = (op == MUL) ? res * Factor() : res / Factor();
    }
    return res;
}
	
Factor()
{
    int res;

    if(NextToken==OPEN) {
	GetNextToken();
	res = Expr();
	if(NextToken!=CLOSE) {
	    fprintf(stderr, "Falta cierre parentesis\n");
	    longjmp(syn_error, 1);
	}
	GetNextToken();
	return res;
    }
    else if(NextToken==INT) {
	res = atoi(TokName);
	GetNextToken();
	return res;
    }
    else if(NextToken==ID) {
	fprintf(stderr, "Todavia no se tratar variables!\n");
	longjmp(syn_error, 1);
    }
    else longjmp(syn_error, 1);
}
