/**************************************************/
/**** Author:       Joel Castellanos           ****/
/**** Course:       CS-241                     ****/
/**** Updated:      02/05/2009                 ****/  
/**************************************************/

//***************************************************************
// This program accepts a postfix expression in the form of a 
// single quoted string and prints the result of the expression 
// to the standard output device with 3 decimal places.
// All calculations are preformed using the float data type. 
//**************************************************************
#include <stdio.h>
int main(int argc, char *argv[])
{ int i=0;  //loop index
  float tempNum = 0.0; //Temporary variable used to build up 
                       //multi-digit-numbers from characters that 
                       //are examined from left to right from the 
                       //input string.

  int buildingNum = 0; //Flag. True if the last character examined 
                       //is part of a number.

  int decimalPlace = 0;//Inverse of the value of the next decimal place
                       //that will be applied to the next digit read.
                       //Zero if the last character was not part of a  
                       //number or if a decimal place has not yet been
                       //read as part of the current number.

  int unaryMinus = 0;  //Flag. True if the current number being read 
                       //is negitive.

  float stack[25];     //Only numbers are placed on the stack.

  int stackTop = 0;    //Index of the location where the next push will
                       //place the number.
  
  if (argc != 2)
  { printf("Error*** postfixCalculator takes exactly one argument.\n");
    return -1;
  }

  char *inputString = argv[1];
  char c = inputString[i];
  while (c)
  { c = inputString[i]; //loop with c='\0' for input of single number
    i++;
    
    if ((c >= '0' && c <= '9') || c == '.')
    { buildingNum = 1;
      if (c == '.')
      { if (decimalPlace)
        { printf("Error*** found number with two decimal points.\n");
          return -1;
        }
        decimalPlace = 1.0;
      }
      else
      { float digitValue = c-'0';
        if (decimalPlace)
        { decimalPlace *=10.0;
          tempNum = tempNum + digitValue/decimalPlace;
        }
        else      
        { tempNum = tempNum*10.0 + digitValue;
        }
      }
    }
    else 
    { //Found a non-digit character therefore, push tempNum.
      if (buildingNum)
      { if (stackTop >= 25)
        { printf("Error*** stack overflow.\n");
          return -1;
        }
        if (unaryMinus) tempNum = -tempNum;
        stack[stackTop] = tempNum;
        stackTop++;

        buildingNum = 0;
        unaryMinus = 0;
        decimalPlace = 0.0;
        tempNum = 0.0;
      }

      if (c == '+' || c == '*' || c == '-' || c == '/')
      { if (c == '-')
        { char next_c = inputString[i];
          if ((next_c >= '0' && next_c <= '9') || next_c == '.')
          { unaryMinus = 1;
          }
        }

        if (!unaryMinus)
        { if (stackTop < 2)
          { printf("Error*** Found a %c when there is %d item on the stack.\n", 
                   c, stackTop);
            return -1;
          }    
      
          float a = stack[stackTop-2];
          float b = stack[stackTop-1];
          float tmp;

          if (c == '+') tmp=a+b;
          else if (c == '-') tmp=a-b;
          else if (c == '*') tmp=a*b;
          else if (c == '/') tmp=a/b;
        
          stack[stackTop-2] = tmp;
          stackTop--;
          //printf("%f %c %f = %f\n", a,c,b, tmp);
        }

      } //end check for +, -, * and /
      else if (c == ' ' || c == '\0') {} //do nothing
      else
      { printf("Error*** unrecognized symbol: %c\n", c);
        return -1;
      }
    } 
  }

  if (stackTop > 1)
  { printf("Error*** Input string ended with nonempty stack.\n");
        return -1;
  }
  printf ("%f\n", stack[stackTop-1]);
  return 0;
}

