#include <iostream>
#include <cstdlib>
#include <cstring>

using namespace std;

#include "Parser.hpp"
#include "Poli.hpp"

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

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

	if (this->eof())
		return tok= ';';

	int c= this->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':
			this->putback(c);
			*this >> dbl;
			return tok= 'n'; 
		case '+':
		case '-':
		case ';':
			return tok= c;
		case 'x':
		case 'X':
			return tok= 'x';
		default:
			return tok= '#';
		}
}

char Parser::Tok() const		// ultima entidad sintactica leida
{
	return tok;
}

double Parser::Dbl() const		// ultimo numero leido
{
	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::ReadPoli(void)
{
	Poli r;

	double sign= 1;
	if (Tok()=='+')
		Lex();
	else
	if (Tok()=='-') {
		sign= -1;
		Lex();
	}
	
	double co;
	int	ex;
	ReadTerm(co,ex);
	r+= Term(sign*co,ex);

	while (Tok()=='+' || Tok()=='-') {
			if (Tok()== '+')
				sign= 1;
			else
				sign= -1;
			Lex();
			ReadTerm(co,ex);
			r+= Term(sign*co,ex);
	} 

	if (Tok()!=';') {
		cerr << "ERROR - polinomio mal escrito\n";
		r= Poli();
	}
	return r;
}

