// L-15 MCS 360 Mon 27 Sep 2010 : infix_to_postfix.cpp

/* This file defines the operators and the methods of the
   class Infix_to_Postfix. */

#include "Infix_to_Postfix.h"
#include <iostream>

#define verbose 1

const std::string Infix_to_Postfix::operators = "+-*/";

bool Infix_to_Postfix::is_operator(char c)
{
   return (operators.find(c) != std::string::npos);
}

int Infix_to_Postfix::precedence_operator(char c)
{
   if(c == '+' || c == '-')
      return 1;
   else
      return 2;
}

void Infix_to_Postfix::process_operator(char c)
{
   if(this->operator_stack.empty())
   {
      if(verbose) std::cout << "pushing " << c << std::endl;
      this->operator_stack.push(c);
   }
   else
   {
      char top_op = this->operator_stack.top();
      if(precedence_operator(c) > precedence_operator(top_op))
      {
         if(verbose) std::cout << "pushing " << c << std::endl;
         this->operator_stack.push(c);
      }
      else
      {
         do
         {
            if(verbose) std::cout << "popping " << top_op << std::endl;
            this->postfix_expression << top_op << " ";           
            this->operator_stack.pop();
            if(this->operator_stack.empty()) break;
            top_op = this->operator_stack.top();
         }
         while(precedence_operator(c) <= precedence_operator(top_op));
         if(verbose) std::cout << "pushing " << c << std::endl;
         this->operator_stack.push(c);
      }
   }
}

Infix_to_Postfix::Infix_to_Postfix(std::string s)
{
   expression = s;
}

std::string Infix_to_Postfix::convert()
{
   
   std::istringstream tokens(this->expression);
   char c;

   while(tokens >> c)
      if(is_operator(c))
      {
         process_operator(c);
      }
      else
      {
         tokens.putback(c);
         int operand;
         tokens >> operand;  
         this->postfix_expression << operand << " ";
      }
   while(!this->operator_stack.empty())
   {
      char c = this->operator_stack.top();
      if(verbose) std::cout << "popping " << c << std::endl;
      this->postfix_expression << c << " ";
      this->operator_stack.pop();
   }

   return this->postfix_expression.str();
}

