// postfix.cpp 

#include <iostream>
#include <cctype>
#include "StackType.h"

using namespace std;

void stackView(StackType<int>);


int main() {

  StackType<int> operandsStack;
  int op1, op2, result;
  int num;
  char c,  again;

  //restrict to positive integers so to avoid complication of floats
  //and complication of negative number vs. negation operator.
  cout << "Operands: positive integers." << endl;
  //restrict to binary arithmetic and logical operators to avoid complication
  //of unary operators.
  cout << "Operators: + - * / % && ||" << endl;

  do {
    operandsStack.MakeEmpty();    //not strictly necessary, but good idea
    cout << endl << "Enter postfix expression to be evaluated:" << endl;

    cin.get(c);
    while (c != '\n') {       //until end of line

      while (c == ' ')   //skip blanks
        cin.get(c);

      if (isdigit(c)) {   //if first digit of integer
        cin.putback(c);   //put it back into stream
        cin >> num;       //then get the whole integer
        operandsStack.Push(num);  //and push it onto stack
      }
      else {        //must be an operator
        if (c=='&' || c=='|')
          cin >> c;              //get the second & or | out of the stream
        
        operandsStack.Pop(op2);    //pop the two top values from stack
        operandsStack.Pop(op1);

        switch (c) {                //process them with operator
        case '+': result = op1 + op2;
                  break;
        case '-': result = op1 - op2;
                  break;
        case '*': result = op1 * op2;
                  break;
        case '/': result = op1 / op2;
                  break;
        case '%': result = op1 % op2;
                  break;
        case '&': result = op1 && op2;
                 break;
        case '|': result = op1 || op2;
                 break;
        default: cout << "ERROR.  invalid operator: " << c << endl;
        }

        operandsStack.Push(result);    //push result onto stack
      }

      //optionally show what the contents of the stack are:
      stackView(operandsStack);   

      cin.get(c);
    }

    operandsStack.Pop(result);     //last item on stack
    cout << "= " << result << endl << endl;

    cout << "Again? (y or n): ";
    cin >> again;
    cin.get();   //skip the newline!
  } while (again == 'y');
}


//function to display all values in stack.
//Pops each value, outputs it, pushes onto temp stack.
//then reverse: pop the values off temp stack, push onto original stack.
//Seems like there's an easier way (i.e. directly access the elements of 
//the array that's implementing the stack, but the array is private and
//inaccessible to this client).  The stack class doesn't have a "view"
//member function; that would violate the idea of a stack.

void stackView(StackType<int> myStack) {
  StackType<int> tempStack;
  int val;

  while (!myStack.IsEmpty()) {
    myStack.Pop(val);
    tempStack.Push(val);
  }

  while (!tempStack.IsEmpty()) {
    tempStack.Pop(val);
    cout << val << " ";
    myStack.Push(val);
  }
  cout << endl;
}


/* run with examples on page 211
Also:
2 3 + 4 * 6 4 1 - % 5 2 / && ||
which is the postfix for:
(2+3)*4 || 6%(4-1) && 5/2

equals 1

*/
