### Question:
RPNContext { private RPNOperation compile(RPNFunction function, List<String> tokens) { RPNComboOperation operation = new RPNComboOperation(); while (!tokens.isEmpty()) { String token = tokens.get(0); if (token.isEmpty()) { tokens.remove(0); continue; } switch (identifyToken(token)) { case CONST_NUMBER: tokens.remove(0); try { double value = Double.valueOf(token); operation.mOperations.add((context, stack) -> stack.push(value)); } catch (NumberFormatException e) { throw new RPNSyntaxErrorException(e); } break; case CONST_STRING: tokens.remove(0); try { String value = token.replaceAll("^:", ""); operation.mOperations.add((context, stack) -> stack.push(value)); } catch (NumberFormatException e) { throw new RPNSyntaxErrorException(e); } break; case OPERATOR: tokens.remove(0); operation.mOperations.add(mOperators.get(token)); break; case BRANCH: switch (token) { case "IF": operation.mOperations.add(compileRestOfIfThen(function, tokens)); break; case "CASE": operation.mOperations.add(compileRestOfCaseOf(function, tokens)); break; case "DO": operation.mOperations.add(compileRestOfDoLoop(function, tokens)); break; default: return operation; } break; case VARIABLE: tokens.remove(0); addFunctionVariableDependency(function, token); operation.mOperations.add((context, stack) -> stack.push(context.getVariable(token))); break; case INVALID: throw new RPNSyntaxErrorException("Invalid token \"" + token + "\""); } } return operation; } RPNContext();  RPNContext(RPNContext parent); static boolean isStopSignal(Object x); void didChangeVariable(String key); void addFunctionVariableDependency(RPNFunction function, String variable); void setVariable(String key, @Nullable Object value); @Nullable Object getVariable(String key); void updateRtcVariables(Calendar now); RPNFunction compile(String recipe); static final Object STOP; }### Answer:
@Test void exceptionStackUnderflow() { assertThrows(RPNStackUnderflowException.class, () -> mContext.compile("+").apply(0.0)); }
@Test void exceptionStackOverflow() { String overflowProg = "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"; assertThrows(RPNStackOverflowException.class, () -> mContext.compile(overflowProg).apply(0.0)); }
@Test void exceptionUnknownVariable() { assertThrows(RPNUnknownVariableException.class, () -> mContext.compile("what").apply(0.0)); }
@Test void exceptionSyntaxError() { assertThrows(RPNSyntaxErrorException.class, () -> mContext.compile("CASE").apply(null)); assertThrows(RPNSyntaxErrorException.class, () -> mContext.compile("1 IF 0 ELSE 1").apply(null)); assertThrows(RPNSyntaxErrorException.class, () -> mContext.compile("1 OF 5 ENDOF").apply(null)); }