public static FormulaNode simplify(FormulaNode node) { while(node instanceof GroupNode) { node = ((GroupNode) node).getExpr(); } return node; }
@Override public FormulaNode transform(Function<FormulaNode, FormulaNode> function) { return function.apply(new GroupNode(expr.transform(function))); }
@Override public ColumnPlanNode visitGroup(GroupNode expr) { return expr.accept(this); }
@Override public String toString() { return asExpression(); }
@Override public Slot<ColumnView> visitGroup(GroupNode group) { return group.getExpr().accept(this); }
@Test public void group() { expect("(false||true)&&true", new FunctionCallNode(AND, new GroupNode(new FunctionCallNode(OR, FALSE, TRUE)), TRUE) ); }
private FieldType validateExpr(FormulaNode formulaNode) { if(formulaNode instanceof ConstantNode) { return ((ConstantNode) formulaNode).getType(); } else if(formulaNode instanceof GroupNode) { return validateExpr(((GroupNode) formulaNode).getExpr()); } else if(formulaNode instanceof SymbolNode) { return validateReference(formulaNode); } else if(formulaNode instanceof CompoundExpr) { return validateReference(formulaNode); } else if(formulaNode instanceof FunctionCallNode) { return validateFunctionCall((FunctionCallNode) formulaNode); } else { throw new UnsupportedOperationException("type: " + formulaNode.getClass().getSimpleName()); } }
private FormulaNode primary() { switch (lexer.peek().getType()) { case SYMBOL: if(lexer.peek().getString().matches("t\\d{10}")) { return enumLiteral(); } else { return symbolOrCall(); } case NUMBER: return number(); case BOOLEAN_LITERAL: return booleanLiteral(); case STRING_LITERAL: return stringLiteral(); case PAREN_START: Token openToken = lexer.next(); FormulaNode e = expression(); Token closeToken = expect(TokenType.PAREN_END); return new GroupNode(e, new SourceRange(openToken, closeToken)); default: throw new FormulaSyntaxException(new SourceRange(lexer.peek()), "Expected a symbol, a number, a string, or '('"); } }
private static SimpleCondition parseCondition(FormulaNode node) { if(node instanceof GroupNode) { return parseCondition(((GroupNode) node).getExpr()); } else if(node instanceof FunctionCallNode) { FunctionCallNode callNode = ((FunctionCallNode) node); if(callNode.getFunction() == NotFunction.INSTANCE) { return parseCondition(callNode.getArgument(0)).negate(); } else if(callNode.getArguments().size() == 2) { return parseBinary(((FunctionCallNode) node)); } else { throw new UnsupportedOperationException("function: " + ((FunctionCallNode) node).getFunction()); } } else if(node instanceof CompoundExpr) { return parseEnumCondition((CompoundExpr) node); } else { throw new UnsupportedOperationException("cannot handle expression: " + node); } }
@Test public void parseNested() { expect("(1+2)/3", new FunctionCallNode(ArithmeticFunctions.DIVIDE, new GroupNode( new FunctionCallNode(ArithmeticFunctions.BINARY_PLUS, new ConstantNode(1), new ConstantNode(2))), new ConstantNode(3))); }
private static void parse(List<SimpleCondition> conditions, Set<Criteria> criteria, FormulaNode node) { if(node instanceof GroupNode) { parse(conditions, criteria, ((GroupNode) node).getExpr()); return; } if(node instanceof FunctionCallNode) { FunctionCallNode call = (FunctionCallNode) node; if (call.getFunction() == AndFunction.INSTANCE) { criteria.add(Criteria.ALL_TRUE); parse(conditions, criteria, call.getArgument(0)); parse(conditions, criteria, call.getArgument(1)); return; } else if (call.getFunction() == OrFunction.INSTANCE) { criteria.add(Criteria.ANY_TRUE); parse(conditions, criteria, call.getArgument(0)); parse(conditions, criteria, call.getArgument(1)); return; } } conditions.add(parseCondition(node)); }
@Test public void parseSimple() { expect("1", new ConstantNode(1)); expect("(1)", new GroupNode(new ConstantNode(1))); expect("1+2", new FunctionCallNode(PLUS, new ConstantNode(1), new ConstantNode(2))); }
FormulaNode expr = groupNode.getExpr(); xpath.append("("); appendTo(expr, xpath);
private List<ResourceId> getFieldIds(FormulaNode formulaNode) { List<ResourceId> fieldIds = new ArrayList<>(); if (formulaNode instanceof FunctionCallNode) { FunctionCallNode functionCall = (FunctionCallNode) formulaNode; for(FormulaNode arg : functionCall.getArguments()) { fieldIds.addAll(getFieldIds(arg)); } } else if (formulaNode instanceof SymbolNode) { SymbolNode symbolNode = (SymbolNode) formulaNode; fieldIds.add(ResourceId.valueOf(symbolNode.getName())); } else if (formulaNode instanceof ConstantNode) { ConstantNode constantNode = (ConstantNode) formulaNode; if (constantNode.getType() instanceof EnumType) { fieldIds.add(ResourceId.valueOf(constantNode.toString())); } } else if (formulaNode instanceof CompoundExpr) { CompoundExpr compoundExpr = (CompoundExpr) formulaNode; fieldIds.addAll(getFieldIds(compoundExpr.getValue())); fieldIds.addAll(getFieldIds(compoundExpr.getField())); } else if (formulaNode instanceof GroupNode) { GroupNode groupNode = (GroupNode) formulaNode; fieldIds.addAll(getFieldIds(groupNode.getExpr())); } return fieldIds; }