
import java.util.StringTokenizer;

/**
 * Calculator implements a RPN calculator that can act on rational values
 */
public class Calculator
{
    private RationalStack stack = new RationalStack();

    /**
     * pushOperand adds the given token to the top of the RationalStack object
     * @param val the token to add
     */
    private void pushOperand(String val)
    {
        StringTokenizer tokens = new StringTokenizer(val, "/");
        if (tokens.hasMoreElements())
        {
            int num = Integer.parseInt(tokens.nextToken());
            int denom = 1;
            if (tokens.hasMoreElements())
            {
                denom = Integer.parseInt(tokens.nextToken());
            }
            stack.push(new Rational(num, denom));
        }
    }

    /**
     * doOperator performs the action specified by op on the top two elements
     * of the RationalStack object
     * @param op the operator to perform
     */
    private void doOperator(String op)
    {
        if (stack.size() < 2)
            return;

        Rational two = stack.pop();
        Rational one = stack.pop();
        Rational result = new Rational();
        if (op.equals("+"))
            result = one.add(two);
        else if (op.equals("-"))
            result = one.subtract(two);
        else if (op.equals("*"))
            result = one.multiply(two);
        else if (op.equals("\\"))
            result = one.divide(two);
        stack.push(result);
    }

    /**
     * run will evaluate the RPN expression and print its result
     * @param expression the expression to evaluate
     */
    public void run(String expression)
    {
        StringTokenizer tokens = new StringTokenizer(expression, " ");
        while (tokens.hasMoreTokens())
        {
            String item = tokens.nextToken();
            if (item.equals("+") || item.equals("-") ||
                item.equals("*") || item.equals("\\"))
            {
                doOperator(item);
            }
            else
            {
                pushOperand(item);
            }
        }
        
        if (stack.size() != 1)
        {
            System.out.println("Warning: malformed expression");
        }
        if (!stack.isEmpty())
        {
            System.out.println("Result is: " + stack.pop());
        }
    }
}
