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.


CREATE OR REPLACE FUNCTION rpn_calc(str VARCHAR2) RETURN NUMBER AS
  TYPE  num_aa    IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
  TYPE  num_stack IS RECORD (a num_aa, top PLS_INTEGER DEFAULT 0);
  ns    num_stack;
  pos1  INTEGER := 1;
  pos2  INTEGER;
  token VARCHAR2(100);
  op2   NUMBER;
  PROCEDURE push(s IN OUT NOCOPY num_stack, x NUMBER) IS
    BEGIN
      s.top := s.top + 1;
      s.a(s.top) := x;
    END;
  FUNCTION pop(s IN OUT NOCOPY num_stack) RETURN NUMBER IS
      x NUMBER;
    BEGIN
      x := s.a(s.top);
      s.top := s.top - 1;
      RETURN x;
    END;
  PROCEDURE print_stack(s num_stack) IS  -- for debugging only; remove from final version
      ps VARCHAR2(4000);
    BEGIN 
      FOR i IN 1 .. s.top LOOP
        ps := ps || s.a(i) || ' ';
      END LOOP;
      DBMS_OUTPUT.put_line('Stack: ' || RTRIM(ps));
    END;
BEGIN
  WHILE pos1 <= LENGTH(str) LOOP
    pos2  := INSTR(str || ' ', ' ', pos1);
    token := SUBSTR(str, pos1, pos2 - pos1);
    pos1  := pos2 + 1;
    CASE token 
         WHEN '+' THEN push(ns, pop(ns) + pop(ns));
         WHEN '-' THEN op2 := pop(ns); push(ns, pop(ns) - op2);
         WHEN '*' THEN push(ns, pop(ns) * pop(ns));
         WHEN '/' THEN op2 := pop(ns); push(ns, pop(ns) / op2);
         WHEN '^' THEN op2 := pop(ns); push(ns, POWER(pop(ns), op2));
         ELSE push(ns, TO_NUMBER(token));
    END CASE;
    print_stack(ns);    -- for debugging purposes only
  END LOOP;
  RETURN pop(ns);
END rpn_calc;
/