#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include <cctype>

using namespace std;

class Parser {
    private:
       istream* is;
       string    tok;
       double    num;
    public:
       Parser(istream*);
       string Read();
       string Tok() const;
       double Num() const;
       void Param();
       void Prim();
       void Factor();
       void Term();
       void Expr();
       void Error(string msg);
       void Semicolon();
};


Parser::Parser(istream* f)
{
    is= f;
}


string Parser::Read()
{
    int c;
    tok= "";

    while ( (c= is->get()) != EOF && isspace(c)  )
        ; 

    if (c==EOF)
       return tok= "#EOF";

    if (isdigit(c))
       {
        is->putback(c);
        *is >> num;
        return tok= "#NUM";
       }

    if (isalpha(c))
       {
        do {
           tok+= c; 
           c= is->get();
        } while (isalpha(c));         
        is->putback(c);
        return tok;
       }

    switch (c)
       {
        case '+':
        case '-':
        case '*':
        case '/':
        case '^': 
        case ';': 
        case '(':
        case ')':  return tok+= c;
        
        default:   return "#ERR";
       }
}

string Parser::Tok() const
{
   return tok;
}

double Parser::Num() const
{
   return num;
}

void Parser::Param()
{
   if (Tok()=="(")
      {
       Read();
       Expr();
       if (Tok()==")")
         {
          Read();
          return;
         }
       else
         Error("Falta '('");
      }
   else
      Error("Falta '('");
}

void Parser::Prim()
{
   if (Tok()=="+")
      {
       Read();
       Prim();
      }
   else
   if (Tok()=="-")
      {
       Read();
       Prim();
      }
   else
   if (Tok()=="#NUM")
      {
       Read();
       return;
      }
   else
   if (Tok()=="sin")
      {
       Read();
       Prim();
       return;
      }
   else
   if (Tok()=="cos")
      {
       Read();
       if (Tok()=="(")
         {
          Read();
          Expr();
          if (Tok()==")")
            {
             Read();
             return;
            }
          else
             Error("Falta ')'");
         }
       else
         Error("Falta'('");
      }
   else
   if (Tok()=="x")
      {
       Read();
       return;
      }
   else
   if (Tok()=="(")
      {
       Read();
       Expr();
       if (Tok()==")")
          Read();
       else
          Error("Falta ')'");
      }
   else
      Error("Falta <Primario>");
}

void Parser::Factor()
{
   Prim();
   while (Tok()=="^")
      {
       Read();
       Prim();
      }
}

void Parser::Term()
{
   Factor();
   for (;;)
      if (Tok()=="*")
         {
          Read();
          Factor();
         }
      else
      if (Tok()=="/")
         {
          Read();
          Factor();
         }
      else
         break;
}


void Parser::Expr()
{
   Term();
   for (;;)
      if (Tok()=="+")
         {
          Read();
          Term();
         }
      else
      if (Tok()=="-")
         {
          Read();
          Term();
         }
      else
         break;
}

void Parser::Error(string msg)
{
    cerr << "ERROR - " << msg << endl;
    cerr << "Ultimo simbolo: " << Tok() << endl;
}

void Parser::Semicolon()
{
    while (Tok()!=";")
       Read();
}

int main()
{
   Parser p= &cin;

   while (p.Read() != "#EOF")
      {
       p.Expr();
       if (p.Tok()==";")
          cerr << "Expresion bien construida\n";
       else
          {
           cerr << "Expresion mal construida\n";
           p.Semicolon(); 
          }
       p.Read();
      }
}

