Task

Create a stack-based evaluator for an expression in   reverse Polish notation (RPN)   that also shows the changes in the stack as each individual token is processed as a table.



 Assume an input of a correct, space separated, string of tokens of an RPN expression
 Test with the RPN expression generated from the   Parsing/Shunting-yard algorithm   task: 

         3 4 2 * 1 5 - 2 3 ^ ^ / + 

 Print or display the output here


Notes

    ^    means exponentiation in the expression above.
    /    means division.


See also

   Parsing/Shunting-yard algorithm for a method of generating an RPN from an infix expression.
   Several solutions to 24 game/Solve make use of RPN evaluators (although tracing how they work is not a part of that task).
   Parsing/RPN to infix conversion.
   Arithmetic evaluation.


/* NetRexx */
options replace format comments java crossref symbols nobinary
 
numeric digits 20
 
rpnDefaultExpression = '3 4 2 * 1 5 - 2 3 ^ ^ / +'
EODAD = '.*'
 
parse arg rpnString
 
if rpnString = '.' then rpnString = rpnDefaultExpression
if rpnString = '' then do
  say 'Enter numbers or operators [to stop enter' EODAD']:'
  loop label rpnloop forever
    rpnval = ask
    if rpnval == EODAD then leave rpnloop
    rpnString = rpnString rpnval
    end rpnloop
  end
 
rpnString = rpnString.space(1)
say rpnString':' evaluateRPN(rpnString)
 
return
 
-- -----------------------------------------------------------------------------
method evaluateRPN(rpnString) public static returns Rexx
 
  stack = LinkedList()
  op = 0
  L = 'L'
  R = 'R'
  rpnString = rpnString.strip('b')
  say 'Input\tOperation\tStack after'
  loop label rpn while rpnString.length > 0
    parse rpnString token rest
    rpnString = rest.strip('b')
    say token || '\t\-'
    select label tox case token
      when '*' then do
        say 'Operate\t\t\-'
        op[R] = Rexx stack.pop()
        op[L] = Rexx stack.pop()
        stack.push(op[L] * op[R])
        end
      when '/' then do
        say 'Operate\t\t\-'
        op[R] = Rexx stack.pop()
        op[L] = Rexx stack.pop()
        stack.push(op[L] / op[R])
        end
      when '+' then do
        say 'Operate\t\t\-'
        op[R] = Rexx stack.pop()
        op[L] = Rexx stack.pop()
        stack.push(op[L] + op[R])
        end
      when '-' then do
        say 'Operate\t\t\-'
        op[R] = Rexx stack.pop()
        op[L] = Rexx stack.pop()
        stack.push(op[L] - op[R])
        end
      when '^' then do
        say 'Operate\t\t\-'
        op[R] = Rexx stack.pop()
        op[L] = Rexx stack.pop()
        -- If exponent is a whole number use Rexx built-in exponentiation operation, otherwise use Math.pow()
        op[R] = op[R] + 0
        if op[R].datatype('w') then stack.push(op[L] ** op[R])
        else stack.push(Rexx Math.pow(op[L], op[R]))
        end
      otherwise do
        if token.datatype('n') then do
          say 'Push\t\t\-'
          stack.push(token)
          end
        else do
          say 'Error\t\t\-'
          end
        end
      end tox
      calc = Rexx
      say stack.toString
    end rpn
    say
    calc = stack.toString
  return calc
 