@Override public Token<Double> evaluate(StellarParser.DoubleLiteralContext context, FrameContext.Context contextVariety) { if (context == null) { throw new IllegalArgumentException("Cannot evaluate a context that is null."); } return new Token<>(Double.parseDouble(context.getText()), Double.class, contextVariety); } }
@Override public Token<Integer> evaluate(StellarParser.IntLiteralContext context, FrameContext.Context contextVariety) { if (context == null) { throw new IllegalArgumentException("Cannot evaluate a context that is null."); } return new Token<>(Integer.parseInt(context.getText()), Integer.class, contextVariety); } }
@Override public void exitNaNArith(StellarParser.NaNArithContext ctx) { expression.tokenDeque.push(new Token<>(Double.NaN, Double.class, getArgContext())); }
@Override public void exitInExpressionStatement(StellarParser.InExpressionStatementContext ctx) { final FrameContext.Context context = getArgContext(); expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> { Token<?> left = popDeque(tokenDeque); Token<?> right = popDeque(tokenDeque); tokenDeque.push(new Token<>(handleIn(left, right), Boolean.class, context)); }, DeferredFunction.class, context)); }
@Override @SuppressWarnings("unchecked") public void exitNotFunc(StellarParser.NotFuncContext ctx) { final FrameContext.Context context = getArgContext(); expression.tokenDeque.push(new Token<>((tokenDeque, state) -> { Token<Boolean> arg = (Token<Boolean>) popDeque(tokenDeque); Boolean v = Optional.ofNullable(ConversionUtils.convert(arg.getValue(), Boolean.class)).orElse(false); tokenDeque.push(new Token<>(!v, Boolean.class, context)); }, DeferredFunction.class, context)); }
@SuppressWarnings("ReferenceEquality") private void exitLambdaVariables() { Token<?> t = expression.tokenDeque.pop(); LinkedList<String> variables = new LinkedList<>(); for (; !expression.tokenDeque.isEmpty() && t != LAMBDA_VARIABLES; t = expression.tokenDeque.pop()) { variables.addFirst(t.getValue().toString()); } expression.tokenDeque.push(new Token<>(variables, List.class, getArgContext())); }
@Override public void exitNInExpressionStatement(StellarParser.NInExpressionStatementContext ctx) { final FrameContext.Context context = getArgContext(); expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> { Token<?> left = popDeque(tokenDeque); Token<?> right = popDeque(tokenDeque); tokenDeque.push(new Token<>(!handleIn(left, right), Boolean.class, context)); }, DeferredFunction.class, context)); }
/** * If we see an identifier, an argument for an inclusion/exclusion predicate, then we want to just push it onto the * stack without its ':'. * @param ctx */ @Override public void exitIdentifier(WindowParser.IdentifierContext ctx) { if(checkForException(ctx)) { return; } stack.push(new Token<>(ctx.getText().substring(1), String.class )); }
@Override public void exitExistsFunc(StellarParser.ExistsFuncContext ctx) { final FrameContext.Context context = getArgContext(); expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> { String variable = ctx.getChild(2).getText(); boolean exists = state.variableResolver.resolve(variable) != null; tokenDeque.push(new Token<>(exists, Boolean.class, context)); }, DeferredFunction.class, context)); String variable = ctx.getChild(2).getText(); expression.variablesUsed.add(variable); }
@Override public void exitLogicalExpressionAnd(StellarParser.LogicalExpressionAndContext ctx) { final FrameContext.Context context = getArgContext(); popArgContext(); final FrameContext.Context parentContext = getArgContext(); expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> { Token<?> left = popDeque(tokenDeque); Token<?> right = popDeque(tokenDeque); tokenDeque.push(new Token<>(booleanOp(left, right, (l, r) -> l && r, "&&"), Boolean.class, parentContext)); }, DeferredFunction.class, context)); expression.tokenDeque.push(new Token<>(new ShortCircuitFrame(), ShortCircuitFrame.class, context)); }
@Override public void exitLogicalExpressionOr(StellarParser.LogicalExpressionOrContext ctx) { final FrameContext.Context context = getArgContext(); popArgContext(); final FrameContext.Context parentContext = getArgContext(); expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> { Token<?> left = popDeque(tokenDeque); Token<?> right = popDeque(tokenDeque); tokenDeque.push(new Token<>(booleanOp(left, right, (l, r) -> l || r, "||"), Boolean.class, parentContext)); }, DeferredFunction.class, context)); expression.tokenDeque.push(new Token<>(new ShortCircuitFrame(), ShortCircuitFrame.class, context)); }
@Override public void exitIf_expr(StellarParser.If_exprContext ctx) { expression.tokenDeque.push(new Token<>(new IfExpr(), IfExpr.class, getArgContext())); }
@Override public void exitArithExpr_plus(StellarParser.ArithExpr_plusContext ctx) { final FrameContext.Context context = getArgContext(); expression.tokenDeque.push(new Token<>((tokenDeque, state) -> { Pair<Token<? extends Number>, Token<? extends Number>> p = getArithExpressionPair(tokenDeque); tokenDeque.push(arithmeticEvaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.addition(context), p)); }, DeferredFunction.class, context)); }
@Override public void exitArithExpr_div(StellarParser.ArithExpr_divContext ctx) { final FrameContext.Context context = getArgContext(); expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> { Pair<Token<? extends Number>, Token<? extends Number>> p = getArithExpressionPair(tokenDeque); tokenDeque.push(arithmeticEvaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.division(context), p)); }, DeferredFunction.class, context)); }
@Override public void exitArithExpr_mul(StellarParser.ArithExpr_mulContext ctx) { final FrameContext.Context context = getArgContext(); expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> { Pair<Token<? extends Number>, Token<? extends Number>> p = getArithExpressionPair(tokenDeque); tokenDeque.push(arithmeticEvaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.multiplication(context), p)); }, DeferredFunction.class, context)); }
@Override public void exitB_expr(StellarParser.B_exprContext ctx) { if(ctx.getParent() instanceof StellarParser.LogicalExpressionOrContext || ctx.getParent() instanceof StellarParser.LogicalExpressionAndContext ) { //we want to know when the argument to the boolean expression is complete expression.tokenDeque.push(new Token<>(new BooleanArg(), BooleanArg.class, getArgContext())); } }
@Test public void verifyHappyPathEvaluation() throws Exception { when(context.getText()).thenReturn("100L"); Token<? extends Number> evaluated = evaluator.evaluate(context, null); assertEquals(new Token<>(100L, Long.class, null), evaluated); verify(context).getText(); verifyNoMoreInteractions(context); }
@Test public void verifyHappyPathEvaluation() throws Exception { when(context.getText()).thenReturn("100"); Token<? extends Number> evaluated = evaluator.evaluate(context, null); assertEquals(new Token<>(100, Integer.class, null), evaluated); verify(context).getText(); verifyNoMoreInteractions(context); }
@Test public void verifyHappyPathEvaluation() throws Exception { when(context.getText()).thenReturn("100f"); Token<? extends Number> evaluated = evaluator.evaluate(context, null); assertEquals(new Token<>(100f, Float.class, null), evaluated); verify(context).getText(); verifyNoMoreInteractions(context); }
@Test public void verifyHappyPathEvaluation() throws Exception { when(context.getText()).thenReturn("100D"); Token<? extends Number> evaluated = evaluator.evaluate(context, null); assertEquals(new Token<>(100D, Double.class, null), evaluated); verify(context).getText(); verifyNoMoreInteractions(context); }