115 lines
3.2 KiB
Java
115 lines
3.2 KiB
Java
package expression;
|
|
|
|
import java.math.BigDecimal;
|
|
import java.math.BigInteger;
|
|
import java.util.List;
|
|
|
|
/**
|
|
* @author Doschennikov Nikita (me@fymio.us)
|
|
*/
|
|
public abstract class AbstractBinaryOperation extends AbstractExpression {
|
|
|
|
protected final AbstractExpression left;
|
|
protected final AbstractExpression right;
|
|
|
|
protected AbstractBinaryOperation(
|
|
AbstractExpression left,
|
|
AbstractExpression right
|
|
) {
|
|
this.left = left;
|
|
this.right = right;
|
|
}
|
|
|
|
protected abstract String getOperator();
|
|
|
|
protected abstract int getPriority();
|
|
|
|
protected abstract boolean isRightAssoc();
|
|
|
|
protected abstract int applyInt(int a, int b);
|
|
|
|
protected abstract BigInteger applyBi(BigInteger a, BigInteger b);
|
|
|
|
protected abstract BigDecimal applyBd(BigDecimal a, BigDecimal b);
|
|
|
|
@Override
|
|
public int evaluate(int x) {
|
|
return applyInt(left.evaluate(x), right.evaluate(x));
|
|
}
|
|
|
|
@Override
|
|
public int evaluate(int x, int y, int z) {
|
|
return applyInt(left.evaluate(x, y, z), right.evaluate(x, y, z));
|
|
}
|
|
|
|
@Override
|
|
public int evaluate(List<Integer> vars) {
|
|
return applyInt(left.evaluate(vars), right.evaluate(vars));
|
|
}
|
|
|
|
@Override
|
|
public BigInteger evaluateBi(List<BigInteger> vars) {
|
|
return applyBi(left.evaluateBi(vars), right.evaluateBi(vars));
|
|
}
|
|
|
|
@Override
|
|
public BigDecimal evaluateBd(List<BigDecimal> vars) {
|
|
return applyBd(left.evaluateBd(vars), right.evaluateBd(vars));
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "(" + left + " " + getOperator() + " " + right + ")";
|
|
}
|
|
|
|
@Override
|
|
public String toMiniString() {
|
|
return miniLeft() + " " + getOperator() + " " + miniRight();
|
|
}
|
|
|
|
private String miniLeft() {
|
|
if (
|
|
left instanceof AbstractBinaryOperation op &&
|
|
op.getPriority() < getPriority()
|
|
) {
|
|
return "(" + op.toMiniString() + ")";
|
|
}
|
|
return left.toMiniString();
|
|
}
|
|
|
|
private String miniRight() {
|
|
if (right instanceof AbstractBinaryOperation op) {
|
|
boolean samePriority = op.getPriority() == getPriority();
|
|
boolean lowerPriority = op.getPriority() < getPriority();
|
|
boolean needParens =
|
|
lowerPriority ||
|
|
(samePriority && isRightAssoc()) ||
|
|
(samePriority && op.isRightAssoc() && getPriority() > 1) ||
|
|
(samePriority &&
|
|
!getOperator().equals(op.getOperator()) &&
|
|
!op.isRightAssoc() &&
|
|
!isRightAssoc());
|
|
if (needParens) {
|
|
return "(" + op.toMiniString() + ")";
|
|
}
|
|
}
|
|
return right.toMiniString();
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object obj) {
|
|
if (this == obj) return true;
|
|
if (obj == null || getClass() != obj.getClass()) return false;
|
|
AbstractBinaryOperation other = (AbstractBinaryOperation) obj;
|
|
return left.equals(other.left) && right.equals(other.right);
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return (
|
|
31 * (31 * left.hashCode() + right.hashCode()) +
|
|
getClass().hashCode()
|
|
);
|
|
}
|
|
}
|