PLACE
spec
solutions
Python

RPN Calculator in Python

This implementation is a stack-based one. It repeatedly calls the raw_input() built-in function to read a line from the standard input, then transforms that line into a list of tokens. The latter is done by the split() method of the module string. The resulting list is fed to the for loop so that the individual tokens become the successive values of tk. An empty input line produces an empty list, for which the for loop does nothing.

All intermediate results in the course of evaluating an expression are stored in st – a list of numbers used as a stack.

If tk is one of '+', '-', '*', or '/', then finding it in the ops dictionary is successful. The two topmost numbers are popped off st, the arithmetic function corresponding to tk is obtained from ops and applied to them. If tk is not an operator, it is expected to contain a number. Whatever the case, a numeric result z is eventually produced and pushed onto the stack.

Nominally, the program is an endless loop with all its actual content placed within a try block. Upon encountering end of input, raw_input() raises the EOFError exception, which is handled by breaking the loop and eventually terminating the program.

Other exceptions may take place due to erroneous input. For example, if tk is neither an operator nor a number, the call of float, instead of producing a number, fails by raising ValueError. Calling pop raises IndexError if st is empty, showing an insufficient number of arguments for a particular arithmetic operator. Also, the assert statement raises AssertionError when the stated condition does not hold, indicating the presence of too few operators in an expression. For all these exceptions there is one universal handler which prints an error message and (implicitly) resumes the main loop.

import string, operator
ops = {'+': operator.add, '-': operator.sub, '*': operator.mul, '/': operator.div}
while True:
  try:
    st = []
    for tk in string.split(raw_input()):
      if tk in ops:
        y,x = st.pop(),st.pop()
        z = ops[tk](x,y)
      else:
        z = float(tk)
      st.append(z)
    assert len(st)<=1
    if len(st)==1: print(st.pop())
  except EOFError:  break
  except:  print('error')

boykobbatgmaildotcom