
/**************************************************************************************************/
/*                                                                                                */
/*  Name:  DarC KonQuesT                                                                          */
/*  Program:  #4                                                                                  */
/*  Date:  2005.3.11                                                                              */
/*  Purpose:                                                                                      */
/*    Implementation file for the expression class.  Allows for manipulation and conversion of    */
/*  infix to postfix expressions.                                                                 */
/*                                                                                                */
/*                                                                                                */
/**************************************************************************************************/

#include <iostream>
#include <fstream>
#include "expression.h"


using namespace std;

/*  Name: expression() ~ constructors                                                                                 */
/*  Purpose:  Initialize values to be used by expression class - pfx and infix.                                       */
/*  Parameters:  None                                                                                                 */
/*  Preconditions:  None                                                                                              */
/*  Postconditions:  pfx and infix variables are initialized to blank values                                          */

expression::expression()
{
  pfx = "";
  infix = "";
}


/*  Name:  getInfix(string)                                                                                           */
/*  Purpose:  Retrieve infix expression from a file and store in a queue                                              */
/*  Parameters:  string in_file - specifies file to open                                                              */
/*  Preconditions:  in_file must be retrieved and passed to function                                                  */
/*  Postconditions:  input file is parsed and infix equations are loaded into queue                                   */

void expression::getInfix(string in_file)
{
  ifstream instream;
  char in_char;
  
  instream.open(in_file.c_str()); //Open file
  if(!instream) { //Make sure it exists
    cerr << "Error: Can't open file - Are your parameters correct?" << endl;
    return;
  }
  while(instream)
  {
    infix = "";
    while(instream >> in_char)
    {
      if(in_char != ';' && in_char != '.')
        infix += in_char;
      else if(in_char == ';')
      {
        punctuation_stack.push(';');
        infix_q.push(infix);
        infix = "";
      }
        
      else if(in_char == '.')
      {
        punctuation_stack.push('.');
        infix_q.push(infix);
        instream.close();
        break;
      }
     }
  }
}
 
  
/*  Name:  showInfix()                                                                                                */
/*  Purpose:  Return the infix equation string appended to a label                                                    */
/*  Parameters:  None                                                                                                 */
/*  Preconditions:  expression class defined, infix queue declared and initialized                                    */
/*  Postconditions:  infix equation is returned to caller                                                             */

string expression::showInfix()
{
  string temp = "Infix:  ";
  temp += infix_q.front();
  temp += punctuation_stack.front();
  punctuation_stack.pop();
  return (temp);
}

/*  Name:  showPostFix(string)                                                                                        */
/*  Purpose:  output postfix equation into a ofstream - into a file                                                   */
/*  Parameters:  string out_file ~ denotes filename to write output into.                                             */
/*  Preconditions:  out_file must be declared, initialized, and filled with an argv[] component                       */
/*  Postconditions:                                                                                                   */

void expression::showPostfix(string out_file)
{
  ofstream outstream;
  outstream.open(out_file.c_str()); //Open file
    if(!outstream) { //Make sure it exists
      cerr << "Error: Can't open file - Are your parameters correct?" << endl;
    }
    
  
  while(!infix_q.empty())
  {
    outstream << showInfix() << endl; 
    outstream << "Postfix:  " << convertToPostfix(infix_q.front()) << endl;
    infix_q.pop();
  }
  outstream.close();
}

/*  Name:  convertToPostfix(string)                                                                                   */
/*  Purpose:  convert an infix string into a postfix string using a queue                                             */
/*  Parameters:  string infix ~ contains infix string to be converted postfix                                         */
/*  Preconditions:  string infix must be declared, initialized, and filled with the infix expression.                 */
/*  Postconditions:  a postfix equation, derived from the infix string is returned.                                   */

string expression::convertToPostfix(string infix)
{
  pfx = "";
    while(!op_stack.empty())
      op_stack.pop();
  
  for(int i = 0; i < infix.size(); i++)
  {
    if(infix[i] >= 'A' && infix[i] <= 'Z')
      pfx += infix[i];
    else if(infix[i] == '(')
      op_stack.push('('); 
    else if(infix[i] == ')')
    {
      while(op_stack.top() != '(') 
      {
           pfx += op_stack.top();
           op_stack.pop();
      }
     op_stack.pop();
    } 
      
    
    else if(infix[i] == '+' || infix[i] == '-' || infix[i] == '*' || infix[i] == '/') 
    {
      if(!op_stack.empty())
        while(precedence(op_stack.top(), infix[i]))
        {
          pfx += op_stack.top();
          op_stack.pop();
          if(op_stack.empty())
            break;
        }
      op_stack.push(infix[i]);
    }
  }
    while(!op_stack.empty())
    {
      pfx += op_stack.top();
      op_stack.pop();
    }
  return pfx;
}

/*  Name:  precedence(char, char)                                                                                     */
/*  Purpose:  determine the precedence of two operators                                                               */
/*  Parameters: char stack_char, char infix                                                                           */
/*  Preconditions:  stack_char and infix must be declared, initialized, and passed.                                   */
/*  Postconditions:  returns TRUE if stack_char has greater or equal precendence to infix.                            */

bool expression::precedence(char stack_char, char infix)
{
  if(stack_char == '(')
    return false;
  else if((stack_char == '+' || stack_char == '-') && (infix == '+' || infix == '-'))
      return true;
  else if((stack_char == '*' || stack_char == '/') && (infix == '-' || infix == '+'))
      return true;
  else if((stack_char == '+' || stack_char == '-') && (infix == '*' || infix == '/'))
      return false;
  else if((stack_char == '*' || stack_char == '/') && (infix == '*' || infix == '/'))
      return true;
  
}

