
de.janno.evaluator.dice.Operator Maven / Gradle / Ivy
package de.janno.evaluator.dice;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.ToString;
import java.util.List;
@EqualsAndHashCode
@ToString
public abstract class Operator {
@NonNull
private final String name;
private final Integer unaryPrecedence;
private final Integer binaryPrecedence;
private final Associativity unaryAssociativity;
private final Associativity binaryAssociativity;
public Operator(@NonNull String name, OperatorType operatorType, @NonNull Associativity associativity, int precedence) {
this(name, getUnaryAssociativity(operatorType, associativity),
getUnaryPrecedence(operatorType, precedence),
getBinaryAssociativity(operatorType, associativity),
getBinaryPrecedence(operatorType, precedence));
}
/**
* The precedence is the priority of the operator.
* An operator with a higher precedence will be executed before an operator with a lower precedence.
* Example : In "1+3*4" * has a higher precedence than +, so the expression is interpreted as 1+(3*4).
* An operator's associativity define how operators of the same precedence are grouped.
*/
public Operator(@NonNull String name, Associativity unaryAssociativity, Integer unaryPrecedence, Associativity binaryAssociativity, Integer binaryPrecedence) {
if (unaryAssociativity == null && binaryAssociativity == null) {
throw new IllegalArgumentException("The operant %s need at least on associativity".formatted(name));
}
this.name = name;
this.unaryAssociativity = unaryAssociativity;
this.binaryAssociativity = binaryAssociativity;
this.unaryPrecedence = unaryPrecedence;
this.binaryPrecedence = binaryPrecedence;
}
private static Associativity getUnaryAssociativity(OperatorType operatorType, @NonNull Associativity associativity) {
if (operatorType == OperatorType.UNARY) {
return associativity;
}
return null;
}
private static Associativity getBinaryAssociativity(OperatorType operatorType, @NonNull Associativity associativity) {
if (operatorType == OperatorType.BINARY) {
return associativity;
}
return null;
}
private static Integer getUnaryPrecedence(OperatorType operatorType, int precedence) {
if (operatorType == OperatorType.UNARY) {
return precedence;
}
return null;
}
private static Integer getBinaryPrecedence(OperatorType operatorType, int precedence) {
if (operatorType == OperatorType.BINARY) {
return precedence;
}
return null;
}
protected static String getBinaryOperatorExpression(String name, List operands) {
return String.format("%s%s%s", operands.get(0).getExpression(), name, operands.get(1).getExpression());
}
protected static String getLeftUnaryExpression(String name, List operands) {
return String.format("%s%s", operands.get(0).getExpression(), name);
}
protected static String getRightUnaryExpression(String name, List operands) {
return String.format("%s%s", name, operands.get(0).getExpression());
}
public abstract @NonNull RollBuilder evaluate(@NonNull List operands) throws ExpressionException;
public boolean supportUnaryOperation() {
return unaryAssociativity != null;
}
public boolean supportBinaryOperation() {
return binaryAssociativity != null;
}
public @NonNull String getName() {
return name;
}
public Associativity getAssociativityForOperantType(OperatorType operatorType) {
if (operatorType == OperatorType.UNARY && unaryAssociativity != null) {
return unaryAssociativity;
}
if (operatorType == OperatorType.BINARY && binaryAssociativity != null) {
return binaryAssociativity;
}
return null;
}
public int getPrecedenceForOperantType(OperatorType operatorType) {
if (operatorType == OperatorType.UNARY && unaryPrecedence != null) {
return unaryPrecedence;
}
if (operatorType == OperatorType.BINARY && binaryPrecedence != null) {
return binaryPrecedence;
}
throw new IllegalStateException("'%s' has no precedence for a operand type of %s".formatted(getName(), operatorType));
}
public enum Associativity {
LEFT,
RIGHT
}
public enum OperatorType {
UNARY(1),
BINARY(2);
public final int argumentCount;
OperatorType(int argumentCount) {
this.argumentCount = argumentCount;
}
public static OperatorType of(int argumentCount) {
if (argumentCount == 1) {
return UNARY;
}
if (argumentCount == 2) {
return BINARY;
}
throw new IllegalArgumentException("OperatorType must have a argumentCount of 1 or 2");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy