#include <iostream>
#include <cstdlib>
#include <sstream>

using namespace std;

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

class Parser : public std::istringstream {
	private:

		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[]);
		int gettok(void);
		void prim(void);
		void factor(void);
		void term(void);
		void expr(void);
	public:
		Parser(std::string);
		void line(void);
};


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

int Parser::gettok(void)
{
	*this >> std::ws;	// se come los blancos
	int ch= get();
	if (isdigit(ch)) {
		putback(ch);
		*this >> 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 Parser::prim(void)
{
	switch(tok) {
		case NUM:	gettok();
					break;
		case VARX:	gettok();
			 		break;
		case VARY:	gettok();
			   		break;
		case LPAR:	gettok();
			  		expr();
			 		if (tok==RPAR) {
						gettok();
						break;
					} 
					else
						error("falta ')'");
		default:	error("se espera <prim>");
	}
}

void Parser::factor(void)
{
	prim();
	while (tok==EXPO) {
		gettok();
		factor();
	}
}

void Parser::term(void)
{
	factor();
	for (;;) 
		switch (tok) {
			case MUL:	gettok();
						factor();
						break;
			case DIV:	gettok();
						factor();
						break;
			default:	return;
		}
}

void Parser::expr(void)
{
	if (tok==ADD) {
		gettok();
		term();
	}
	else
	if (tok==SUB) {
		gettok();
		term();
	}
	else
		term();
	for (;;) 
		switch (tok) {
			case ADD:	gettok();
						term();
						break;
			case SUB:	gettok();
						term();
						break;
			default:	return;
		}
}

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

Parser::Parser(std::string str) : istringstream(str)
{
}


int main(int argc, char** argv) 
{
	std::string linea;
	char ch;
	do {
		std::cin >> ch;
		linea+= ch;
	} while (ch!=';' && ch!='\n');
	Parser p(linea);
	p.line();
	return EXIT_SUCCESS;
}
