consistent toString functions for expressions, parentasis are added if neccessary

This commit is contained in:
wea_ondara
2022-07-14 18:02:18 +02:00
parent 7dafade67a
commit eb5b3a9879
14 changed files with 297 additions and 194 deletions

View File

@@ -20,10 +20,15 @@ public class AndExpression implements Expression {
return Type.AND;
}
@Override
public Priority getPriority() {
return Priority.LOGIC_AND;
}
@Override
public String toString() {
return exprs.stream().map(e -> {
if (e instanceof OrExpression) {
if (e.getPriority().getValue() < getPriority().getValue()) {
return "(" + e + ")";
} else {
return e.toString();

View File

@@ -17,9 +17,31 @@ public class BinaryExpression implements Expression {
return Type.BINARY;
}
@Override
public Priority getPriority() {
return switch (operator) {
case EQ, NE, IS -> Priority.EQUALITY;
case LT, LE, GT, GE -> Priority.RELATIONAL;
case IN -> Priority.RELATIONAL; //or equality?
default -> throw new IllegalStateException();
};
}
@Override
public String toString() {
return left + " " + operator + " " + right;
String ret = "";
if (left.getPriority().getValue() < getPriority().getValue()) {
ret += "(" + left + ")";
} else {
ret += left.toString();
}
ret += " " + operator + " ";
if (right.getPriority().getValue() < getPriority().getValue()) {
ret += "(" + right + ")";
} else {
ret += right.toString();
}
return ret;
}
@AllArgsConstructor
@@ -30,8 +52,10 @@ public class BinaryExpression implements Expression {
LE("<="),
GT(">"),
GE(">="),
// OR("OR"),
// AND("AND"),
//
// ADD("+"),
// SUB("-"),
IN("IN"),
IS("IS"),
;
@@ -48,7 +72,11 @@ public class BinaryExpression implements Expression {
LT, GE,
GE, LT,
LE, GT,
GT, LE);
GT, LE
// ADD, SUB,
// SUB, ADD
);
public Operator invert() {
return INVERSION.get(this);

View File

@@ -20,6 +20,11 @@ public class ConstantExpression implements Expression {
return Type.CONSTANT;
}
@Override
public Priority getPriority() {
return Priority.CONSTANT;
}
@Override
public String toString() {
return value.toString();

View File

@@ -1,8 +1,13 @@
package jef.expressions;
import lombok.AllArgsConstructor;
import lombok.Getter;
public interface Expression {
Type getType();
Priority getPriority();
public enum Type {
AND,
BINARY,
@@ -17,4 +22,28 @@ public interface Expression {
UNARY,
WHERE,
}
@AllArgsConstructor
@Getter
public enum Priority {
UNDEFINED(0),
ASSIGNMENT(1), // =, +=, -=, *=, /=
TERNARY(2), // ? :
LOGIC_OR(3), // ||
LOGIC_AND(4), // &&
BITWISE_OR(5), // |
BITWISE_XOR(6), // ^
BITWISE_AND(7), // &
EQUALITY(8), // ==, !=
RELATIONAL(9), // <, <=, =>, >
BIT_SHIFT(10), // <<, >>
ADD_SUB(13), // +, -
MUL_DIV_MOD(14), // *, /, %
UNARY_PRE(15), // +, -, !, ~, --i, ++i
UNARY_POST(16), // i++, i--
CONSTANT(17), // constant values
;
private final int value;
}
}

View File

@@ -20,8 +20,19 @@ public class OrExpression implements Expression {
return Type.OR;
}
@Override
public Priority getPriority() {
return Priority.LOGIC_OR;
}
@Override
public String toString() {
return exprs.stream().map(Expression::toString).collect(Collectors.joining(" OR "));
return exprs.stream().map(e -> {
if (e.getPriority().getValue() < getPriority().getValue()) {
return "(" + e + ")";
} else {
return e.toString();
}
}).collect(Collectors.joining(" OR "));
}
}

View File

@@ -29,7 +29,7 @@ public class ParameterExpression extends ConstantExpression implements Expressio
} else if (this.value == null) {
return "null";
} else if (this.value instanceof Collection) {
return "(" + ((Collection<?>) this.value).stream().map(Objects::toString).collect(Collectors.joining(", ")) + ")";
return "(" + ((Collection<?>) this.value).stream().map(e -> e == null ? "NULL" : Objects.toString(e)).collect(Collectors.joining(", ")) + ")";
}
return value.toString();
}

View File

@@ -18,6 +18,11 @@ public class SelectExpression implements Expression {
return Type.SELECT;
}
@Override
public Priority getPriority() {
return Priority.UNDEFINED;
}
@Override
public String toString() {
return "SELECT " + fields.stream().map(e -> e.equals("*") ? e : "`" + e + "`").collect(Collectors.joining(", ")) + " FROM "

View File

@@ -15,6 +15,11 @@ public class TernaryExpression implements Expression {
return Type.TERNARY;
}
@Override
public Priority getPriority() {
return Priority.TERNARY;
}
@Override
public String toString() {
return "IF(" + cond + ", " + whenTrue + ", " + whenFalse + ")";

View File

@@ -14,12 +14,17 @@ public class UnaryExpression implements Expression {
return Type.UNARY;
}
@Override
public Priority getPriority() {
return Priority.UNARY_PRE;
}
@Override
public String toString() {
if (expr instanceof ConstantExpression) {
return operator + " " + expr;
} else {
if (expr.getPriority().getValue() < getPriority().getValue()) {
return operator + " (" + expr + ")";
} else {
return operator + " " + expr;
}
}

View File

@@ -14,6 +14,11 @@ public class WhereExpression implements Expression {
return Type.WHERE;
}
@Override
public Priority getPriority() {
return Priority.UNDEFINED;
}
@Override
public String toString() {
return queryable + " WHERE " + where;

View File

@@ -101,6 +101,11 @@ public class ExpressionOptimizerBottomUp extends ExpressionModifier {
&& b.getOperator().isInvertible()) {
//!(a < b) -> a >= b
return new BinaryExpression(b.getLeft(), b.getRight(), b.getOperator().invert());
} else if (inner instanceof BinaryExpression b
&& expr.getOperator() == UnaryExpression.Operator.NOT
&& b.getOperator() == BinaryExpression.Operator.IS) {
//!(a < b) -> a >= b
return new BinaryExpression(b.getLeft(), new UnaryExpression(b.getRight(), UnaryExpression.Operator.NOT), b.getOperator());
} else {
return super.modifyUnary(expr);
}

View File

@@ -10,7 +10,7 @@ import jef.expressions.UnaryExpression;
import java.util.ArrayList;
public class ExpressionOptimizer extends ExpressionModifier {
public class ExpressionOptimizerTopDown extends ExpressionModifier {
@Override
public Expression modifyAnd(AndExpression expr) {
var ands = new ArrayList<Expression>(expr.getExprs().size() * 2);

View File

@@ -6,7 +6,6 @@ import jef.asm.PredicateParser;
import jef.expressions.Expression;
import jef.expressions.SelectExpression;
import jef.expressions.WhereExpression;
import jef.expressions.modifier.ExpressionOptimizer;
import jef.expressions.modifier.ExpressionOptimizerBottomUp;
import jef.expressions.modifier.TableAliasInjector;
import jef.expressions.modifier.TernaryRewriter;