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.


import ceylon.collection {
 
	ArrayList
}
 
shared void run() {
 
	value ops = map {
		"+" -> plus<Float>,
		"*" -> times<Float>,
		"-" -> ((Float a, Float b) => a - b),
		"/" -> ((Float a, Float b) => a / b),
		"^" -> ((Float a, Float b) => a ^ b)
	};
 
	void printTableRow(String|Float token, String description, {Float*} stack) {
		print("``token.string.padTrailing(8)````description.padTrailing(30)````stack``");
	}
 
	function calculate(String input) {
 
		value stack = ArrayList<Float>();
		value tokens = input.split().map((String element) 
			=> if(ops.keys.contains(element)) then element else parseFloat(element));
 
		print("Token   Operation                     Stack");
 
		for(token in tokens.coalesced) {
			if(is Float token) {
				stack.push(token);
				printTableRow(token, "push", stack);
			} else if(exists op = ops[token], exists first = stack.pop(), exists second = stack.pop()) {
				value result = op(second, first);
				stack.push(result);
				printTableRow(token, "perform ``token`` on ``formatFloat(second, 1, 1)`` and ``formatFloat(first, 1, 1)``", stack);
			} else {
				throw Exception("bad syntax");
			}
		}
		return stack.pop();
	}
 
	print(calculate("3 4 2 * 1 5 - 2 3 ^ ^ / +"));
}