#include "ExpressionFactory.h"
#include <stack>
#include <sstream>
#include "Plus.h"
#include "Minus.h"
#include "Multiply.h"
#include "Divide.h"
#include "Number.h"
#include "Variable.h"
#include "NumberFormatException.h"
#include <iostream>

ExpressionFactory::ExpressionFactory()
{
}


ExpressionFactory::~ExpressionFactory(void)
{
}


Expression *ExpressionFactory::parse(std::string expression)
{
    std::stack<Expression *> expressionStack;
    std::istringstream iss(expression);
    std::string token;
    Expression *left, *right, *subExpression;
    do 
    {
        iss >> token;
//        std::cout << " " << token << std::endl;
        if  ((token == "+")||(token == "-")||(token == "*")||(token == "/"))
        {
            right = expressionStack.top(); expressionStack.pop();
            left = expressionStack.top(); expressionStack.pop();
            if (token == "+")
                subExpression = new Plus(left, right);
            else if (token == "-")
                subExpression = new Minus(left, right);
            else if (token == "*")
                subExpression = new Multiply(left, right);
            else if (token == "/")
                subExpression = new Divide(left, right);
            expressionStack.push( subExpression );
        }
        else if (isNumeric(token))
        {
            std::istringstream iss1(token);
            int number;
            iss1 >> number;
            expressionStack.push( new Number( number ) );
        }
        else if (isAlpha(token))
            expressionStack.push( new Variable(token) );
        else
            throw NumberFormatException(token.c_str());
    }
    while (!iss.eof());

    Expression *root = expressionStack.top(); 
    expressionStack.pop();
    return root;
}


bool ExpressionFactory::isNumeric(std::string token)
{
    unsigned int i;
    for (i=0; i<token.length(); i++)
        if ((token[i]<'0')||(token[i]>'9'))
            return false;
    return true;
}

bool ExpressionFactory::isAlpha(std::string token)
{
    unsigned int i;
    for (i=0; i<token.length(); i++)
        if (!( ((token[i]>='a')&&(token[i]<='z')) ||
               ((token[i]>='A')&&(token[i]<='Z')) ||
               (token[i]=='_') ))
            return false;
    return true;
}

