//Infix to Prefix and Postfix Converter
//Shawn O'Neil
#include <iostream>
#include <string>
#include "StringStack.h"
using namespace std;


StringStack::StringStack()
   {
   head = new Node;
   head->setnext(NULL);
   }

StringStack::~StringStack()
   {
   delete head;
   }

void StringStack::push(string s)
   {
   Node *newnode = new Node;
   newnode->setnext(head->getnext());
   head->setnext(newnode);
   newnode->setdata(s);
   }

string StringStack::pop()
   {
   if(head->getnext() != NULL)
      {
      Node *n = head->getnext();
      head->setnext(n->getnext());
      string ret = n->getdata();
      n->setnext(NULL);
      delete n;
      return ret;
      }
   else
      {
      string error = "tried to pop from an empty list";
      return error;
      }
   }

bool StringStack::empty()
   {
   return (head->getnext() == NULL);
   }

Node::Node()
   {

   }

Node::~Node()
   {
   delete next;
   }

void Node::setnext(Node *n)
   {
   next = n;
   }

Node *Node::getnext()
   {
   return next;
   }

void Node::setdata(string s)
   {
   data = s;
   }

string Node::getdata()
   {
   return data;
   }

string peek(StringStack &st);
bool leftFirst(string a, string b);
int rank(string c);
string postfix(string infix);
string prefix(string infix);


//Main Methods, sends the infix expression on to be converted
int main()
   {
   string infix;
   cout << "Enter an infix expression (ctrl-z to quit): ";
   while(getline(cin, infix), cin)
      {
      cout << "Postfix: " << postfix(infix) << endl;
      cout << "Prefix: " << prefix(infix) << endl << endl;
      cout << "Enter an infix expression (ctrl-z to quit): ";
      }
   }


//Converts an infix expression to a postfix expression using two string stacks
string postfix(string infix)
   {
   StringStack postfix;
   StringStack operators;

   for(int i = 0; i < (int)infix.length(); i++)
      {
      char newchar = infix[i];
      if('0' <= newchar && newchar <= '9')
         {
         postfix.push((string)""+newchar);
         }
      else
         {
         string thechar = (string)""+newchar;
         if(operators.empty())
            operators.push(thechar);
         else if(thechar == "(")
            operators.push(thechar);
         else if(thechar == ")")
            {
            while(peek(operators) != "(")
               {
               string a = postfix.pop();
               string b = postfix.pop();
               string c = operators.pop();
               string ba = b+a;
               string bac = ba+c;
               postfix.push(bac);
               }
            operators.pop();
            }
         else
            {
            while(leftFirst(peek(operators), thechar))
               {
               string a = postfix.pop();
               string b = postfix.pop();
               string c = operators.pop();
               string ba = b+a;
               string bac = ba+c;
               postfix.push(bac);
               }
            operators.push(thechar);
            }
         }
      }
   while(!operators.empty())
      {
      string a = postfix.pop();
      string b = postfix.pop();
      string c = operators.pop();
      string ba = b+a;
      string bac = ba+c;
      postfix.push(bac);
      }
   return postfix.pop();
   }


//converts an infix expression to prefix using two string stacks
string prefix(string infix)
   {
   StringStack prefix;
   StringStack operators;

   for(int i = 0; i < (int)infix.length(); i++)
      {
      char newchar = infix[i];
      if('0' <= newchar && newchar <= '9')
         {
         prefix.push((string)""+newchar);
         }
      else
         {
         string thechar = (string)""+newchar;
         if(operators.empty())
            operators.push(thechar);
         else if(thechar == "(")
            operators.push(thechar);
         else if(thechar == ")")
            {
            while(peek(operators) != "(")
               {
               string a = operators.pop();
               string b = prefix.pop();
               string c = prefix.pop();
               string cb = c+b;
               string acb = a+cb;
               prefix.push(acb);
               }
            operators.pop();
            }
         else
            {
            while(leftFirst(peek(operators), thechar))
               {
               string a = operators.pop();
               string b = prefix.pop();
               string c = prefix.pop();
               string cb = c+b;
               string acb = a+cb;
               prefix.push(acb);
               }
            operators.push(thechar);
            }
         }
      }
   while(!operators.empty())
      {
               string a = operators.pop();
               string b = prefix.pop();
               string c = prefix.pop();
               string cb = c+b;
               string acb = a+cb;
               prefix.push(acb);
      }
   return prefix.pop();
   }


//checks to see which of two operator characters is of higher order
bool leftFirst(string a, string b)
   {
   if(a == "#")
      return false;
   if( a == "^" && b == "^")
      return false;
   else if(rank(a) >= rank(b))
      return true;
   return false;
   }

//gives rank to two operator characters, used by leftFirst
int rank(string c)
   {
   if(c == "+" || c == "-")
      return 1;
   else if(c == "*" || c == "/")
      return 2;
   else if(c == "^")
      return 3;
   return 0;
   }

//Peek on a stringstack implemented using empty, pop, and push
string peek(StringStack &st)
   {
   string ret = "#";
   if(!st.empty())
      {
      ret = st.pop();
      st.push(ret);
      }
   return ret;
   }