protected static double calculateRPN(List<Token> rpnSequence) throws CalculationException {
		Stack<Token> calcStack = new Stack<>();
		for (Token node : rpnSequence) {
			if (node instanceof TokenValue) {
				calcStack.push(node);
			} else if (node instanceof TokenComputable) {
				TokenComputable function = (TokenComputable) node;
				if (calcStack.size() < function.args) {
					throw new CalculationException("Wrong number of arguments " +
							calcStack.size() + " to function " + function.notation);
				}
				
				// Read params for the function from the stack
				double[] params = new double[function.args];
				for (int i = function.args-1; i >= 0; i--) {
					Token paramNode = calcStack.pop();
					if (!(paramNode instanceof TokenValue)) {
						throw new CalculationException("Parameter node is not a value");
					}
					params[i] = ((TokenValue)paramNode).value;
				}
				
				// Push back into the stack the result of the function call
				double result = function.compute(params);
				calcStack.push(new TokenValue(result));
			} // Disregard any tokens other than Value or Computable
		}
		if (calcStack.size() != 1) {
			throw new CalculationException("Stack size is " + calcStack.size());
		}
		Token node = calcStack.pop();
		if (!(node instanceof TokenValue)) {
			throw new CalculationException("Last node is not a value");
		}
		return ((TokenValue)node).value;
	}