#include <iostream>
#include <cstdlib>

using namespace std;

#include "Parser.h"

Parser::Parser(istream& s)
{
    is= &s;
    lex();
}

char Parser::lex()
{
    while ( !is->eof() && isspace(is->peek()) )
       is->get(); 

    if (is->eof())
       return tok= '#';

    int c= is->get();      // ultimo caracter leido
    switch (c) {
        case '0': case '1': case '2': case '3': case '4':
        case '5': case '6': case '7': case '8': case '9':
            is->putback(c);
            *is >> dbl;
            return tok= 'n'; 
        case '+':
        case '-':
        case ';':
            return tok= c;
        case 'x':
        case 'X':
            return tok= 'x';
        default:
            return tok= '#';
       }
}

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

double Parser::Dbl() const
{
    return dbl;
}

void Parser::readterm(double& coef, int& expo)
{
   if (Tok() == 'n')
      {
       coef= Dbl();
       lex();
       if (Tok() == 'x')
          {
           lex();
           if (Tok() == 'n')
              {
               expo= (int)Dbl();
               lex();
              }
           else
              expo= 1;
          }
       else
          expo= 0;
      }
   else
      if (Tok() == 'x')
         {
          lex();
          coef= 1.0;
          if (Tok() == 'n')
             {
              expo= (int)Dbl();
              lex();
             }
           else
             expo= 1;
         }
      else
         {
          cerr << "ERROR- se espera termino\n";
          coef= 0;
          expo= 0;
         }
}

Poli Parser::poli()
{
    double sign= 1;
    if (Tok()=='+')
       lex();
    else
      if (Tok()=='-')
         {
          sign= -1;
          lex();
         }
   
    double c;
    int    e;
    readterm(c,e);
    Poli   r(sign*c,e);

    while (Tok()=='+' || Tok()=='-')
       {
        if (Tok()== '+')
           sign= 1;
        else
           sign= -1;
        lex();
        readterm(c,e);
        r+= Term(sign*c,e);
       } 
    if (Tok()==';')
       return r;
    cerr << "ERROR - polinomio mal escrito\n";
    return Poli();
}

