import java.io.*;
import java.util.*;

public class Evaluator {
    Stack stack;
    StringTokenizer st;
    
    public Evaluator (String line) {
	st = new StringTokenizer (line, "+-*/ ", true);
	stack = new Stack ();
    }

    // evaluate: evaluate the expression and return an integer
    // might print a warning message and return or print an
    // error message and quit.
    public int evaluate () {	
	while (st.hasMoreTokens ()) {
	    String token = st.nextToken ();
	    
	    if (isOperand (token)) {
		stack.push (new Integer (token));		
	    } else if (isOperator (token)) {
		handleOperator (token);
	    } else if (isWhitespace (token)) {
		// do nothing
	    } else {
		error ("unrecognized token " + token);
	    }
	}
	
	// get the result
	if (stack.empty ()) error ("no result left on stack.");	
	int result = popInt ();
	
	// if there are extra items on the stack, warn the user and
	// pop the excess
	while (!stack.empty ()) {
	    System.out.print ("Warning: item left on the stack: ");
	    System.out.println (popInt ());
	}  
	return result;
    }

    // handleOperator: perform the given operation and push the result
    private void handleOperator (String token) {
	int op2 = popInt ();
	int op1 = popInt ();
	int res = operate (op1, op2, token);
	stack.push (new Integer (res));
    }

    // operate: perform the given operation on the given operands
    private int operate (int op1, int op2, String token) {
	char operator = token.charAt(0);

	switch (operator) {
	case '+': return op1 + op2;
	case '-': return op1 - op2;
	case '*': return op1 * op2;
	case '/': return op1 / op2;
	default:
	    error ("non-operator in operate.");
	}
	return -1;
    }
    
    // isOperator: check if the token contains a single character that
    // is an operator
    private boolean isOperator (String token) {
	if (token.length() != 1) return false;
	switch (token.charAt(0)) {
	case '+': case '-': case '*': case '/':
	    return true;
	default:
	    return false;
	}
    }

    // isOperand: check if all the characters in the token are digits
    private boolean isOperand (String token) {
	for (int i=0; i<token.length(); i++) {
	    if (!Character.isDigit (token.charAt (i))) {
		return false;
	    }
	}
	return true;
    }
  
    // isWhitespace: check if all the characters in the token are
    // whitespace (spaces, tabs or newlines)
    private boolean isWhitespace (String token) {
	for (int i=0; i<token.length(); i++) {
	    if (!Character.isWhitespace (token.charAt (i))) {
		return false;
	    }
	}
	return true;
    }

    // popInt: pop an item off the stack and extract the int value
    private int popInt () {
	if (stack.empty ()) error ("not enough operands on the stack.");
	return ((Integer) stack.pop()).intValue();
    }

    // error: print an error message and quit
    private void error (String s) {
	System.out.println ("Error: " + s);
	System.exit(1);
    }	
}

