Files
paradigms/java/expression/AbstractBinaryOperation.java
2026-04-08 21:25:17 +03:00

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()
);
}
}