
#include <iostream>
#include <cstdlib>

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;
}

void expr(void);

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

void factor(void)
{
	prim();
	while (tok==EXPO) {
		gettok();
		factor();
		std::cout << "^ ";
	}
}

void term(void)
{
	factor();
	for (;;) 
		switch (tok) {
			case MUL:	gettok();
						factor();
						std::cout << "* ";
						break;
			case DIV:	gettok();
						factor();
						std::cout << "/ ";
						break;
			default:	return;
		}
}

void expr(void)
{
	if (tok==ADD) {
		gettok();
		term();
	}
	else
	if (tok==SUB) {
		gettok();
		term();
		std::cout << "chs ";
	}
	else
		term();
	for (;;) 
		switch (tok) {
			case ADD:	gettok();
						term();
						std::cout << "+ ";
						break;
			case SUB:	gettok();
						term();
						std::cout << "- ";
						break;
			default:	return;
		}
}

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

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