@Override public Boolean visit(final BinaryExpr n1, final Node arg) { final BinaryExpr n2 = (BinaryExpr) arg; if (n1.getOperator() != n2.getOperator()) { return Boolean.FALSE; } if (!nodeEquals(n1.getLeft(), n2.getLeft())) { return Boolean.FALSE; } if (!nodeEquals(n1.getRight(), n2.getRight())) { return Boolean.FALSE; } return Boolean.TRUE; }
// This logically inverts a condition expression, simplifying the AST if possible private static Expression invertCondition(Expression expression) { if (expression instanceof UnaryExpr) { final UnaryExpr unary = (UnaryExpr) expression; // Unary not expression, just remove the not if (unary.getOperator() == UnaryExpr.Operator.not) { return unary.getExpr(); } else { // Else wrap it in a not return new UnaryExpr(expression, UnaryExpr.Operator.not); } } else if (expression instanceof BinaryExpr) { final BinaryExpr binary = (BinaryExpr) expression; final Operator inverted; // For binary compare operators, just use the opposite operator // Boolean operators use De Morgan's law // Other operators use a not operator, but are also enclosed in () switch (binary.getOperator()) { case equals: inverted = Operator.notEquals; break; case notEquals: inverted = Operator.equals; break; case less: inverted = Operator.greaterEquals; break; case greater: inverted = Operator.lessEquals; break; case lessEquals: inverted = Operator.greater; break; case greaterEquals: inverted = Operator.less; break; case or: return new BinaryExpr( invertCondition(binary.getLeft()), invertCondition(binary.getRight()), Operator.and); case and: return new BinaryExpr( invertCondition(binary.getLeft()), invertCondition(binary.getRight()), Operator.or); default: return new UnaryExpr(new EnclosedExpr(binary), UnaryExpr.Operator.not); } return new BinaryExpr(binary.getLeft(), binary.getRight(), inverted); } else if (expression instanceof AssignExpr || expression instanceof ConditionalExpr || expression instanceof InstanceOfExpr) { // This expressions have lower precedence so they need to be enclosed in () return new UnaryExpr(new EnclosedExpr(expression), UnaryExpr.Operator.not); } else { // These are higher precedence, no need for () return new UnaryExpr(expression, UnaryExpr.Operator.not); } }