
#include <iostream>
#include <cstdlib>
#include <cmath>

using namespace std;

const char *name[] = {
	"NUM", "VARX", "VARY", "ADD", "SUB", "MUL", "DIV", "EXPO", 
	"LPAR", "RPAR", "SEMI", "BAD"
};

enum {
	NUM, VARX, VARY, ADD, SUB, MUL, DIV, EXPO, LPAR, RPAR, SEMI, BAD
};

int tok;	// ultimo token leido
double num;	// ultimo numero leido

void error(const char mesg[])
{
	std::cerr << "ERROR - " << mesg << std::endl;
	exit(EXIT_FAILURE);
}

int gettok(void)
{
	std::cin >> std::ws;	// se come los blancos
	int ch= std::cin.get();
	if (isdigit(ch)) {
		std::cin.putback(ch);
		std::cin >> num;
		tok= NUM;
	}
	else
	switch (ch) {
		case 'x':
		case 'X':	tok= VARX;
					break;
		case 'y':
		case 'Y':	tok= VARY;
					break;
		case '+':	tok= ADD;
					break;
		case '-':	tok= SUB;
					break;
		case '*':	tok= MUL;
					break;
		case '/':	tok= DIV;
					break;
		case '^':	tok= EXPO;
					break;
		case '(':	tok= LPAR;
					break;
		case ')':	tok= RPAR;
					break;
		case ';':	tok= SEMI;
					break;
		case EOF:	tok= SEMI;
					break;
		default:	tok= BAD;
					break;
	}
	return tok;
}

double expr(void);

double prim(void)
{
	double p;
	switch(tok) {
		case NUM:	p= num;
					gettok();
			  		break;
		case VARX:	p= 0.0;	
					gettok();
					break;
		case VARY:	p= 0.0;
					gettok();
					break;
		case LPAR:	gettok();
					p= expr();
					if (tok==RPAR) {
						gettok();
				   		break;
			   		} 
			   		else
				   		error("falta ')'");
		default:	p= 0.0;
					error("se espera <prim>");
	}
	return p;
}

double factor(void)
{
	double f= prim();
	while (tok==EXPO) {
		gettok();
		f= pow(f, factor());
	}
	return f;
}

double term(void)
{
	double t= factor();
	for (;;) 
		switch (tok) {
			case MUL:	gettok();
						t*= factor();
						break;
			case DIV:	gettok();
						t/= factor();
						break;
			default:	return t;
		}
	return 0.0;
}

double expr(void)
{
	double e;
	if (tok==ADD) {
		gettok();
		e= term();
	}
	else
	if (tok==SUB) {
		gettok();
		e= -term();
	}
	else
		e= term();
	for (;;) 
		switch (tok) {
			case ADD:	gettok();
						e+= term();
						break;
			case SUB:	gettok();
						e-= term();
						break;
			default:	return e;
		}
	return 0.0;	
}

void line(void)
{
	gettok();
	double L= expr();
	if (tok==SEMI) {
		std::cerr << "La expresion es correcta\n";
		std::cout << L << std::endl;
	}
	else 
		error("falta ';'");
}

int main(int argc, char** argv) 
{
	line();
	return EXIT_SUCCESS;
}
