net.diversionmc.d3.operation.Operator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of D3 Show documentation
Show all versions of D3 Show documentation
Diversion Network Data v3 (D3) standard using Parser API.
The newest version!
package net.diversionmc.d3.operation;
import net.diversionmc.parser.expression.ExpressionPiece;
import net.diversionmc.parser.expression.PieceResult;
import net.diversionmc.parser.pattern.OperationSolver;
import net.diversionmc.parser.util.FilePointer;
import java.util.Arrays;
import java.util.List;
import java.util.function.BinaryOperator;
import static net.diversionmc.d3.D3.simplifyNumber;
import static net.diversionmc.d3.operation.Operator.OperatorType.*;
import static net.diversionmc.parser.expression.NumberPiece.tryBoolean;
import static net.diversionmc.parser.expression.NumberPiece.tryNumber;
import static net.diversionmc.parser.expression.PieceResult.CONTINUE;
import static net.diversionmc.parser.expression.PieceResult.LEAVE;
import static net.diversionmc.parser.util.ParserException.ASSERT;
public class Operator extends ExpressionPiece {
private final StringBuilder sb = new StringBuilder();
private OperatorType type;
public Operator(FilePointer ptr) {
super(ptr);
}
public PieceResult read(char c, FilePointer ptr) {
if (sb.isEmpty()) {
type = from(sb.append(c) + "");
return CONTINUE;
}
// Parse operator string
OperatorType t = from(sb.append(c) + "");
if (t == null) {
ASSERT(type != null, () -> ptr, "unknown operator " + sb + c);
return LEAVE;
}
type = t;
return CONTINUE;
}
public String toString() {
return type + "";
}
public OperatorType type() {
return type;
}
public Operator type(OperatorType t) {
type = t;
return this;
}
public static boolean check(char c) {
return Arrays.stream(values())
.anyMatch(v -> v.operator.indexOf(c) >= 0);
}
private static final OperationSolver.TriOperator solverOperator
= (a, b, op) -> new ValueSentence(a.pointer(), op.type().operate(a + "", b == null ? null : b + ""));
public static final List> solvers = List.of(
new OperationSolver<>(true,
op -> op.type() == POW,
solverOperator),
new OperationSolver<>(false,
op -> op.type() == MUL || op.type() == DIV || op.type() == MOD,
solverOperator),
new OperationSolver<>(false,
op -> op.type() == ADD || op.type() == SUB,
solverOperator),
new OperationSolver<>(false,
op -> op.type() == LES || op.type() == LEQ
|| op.type() == MOR || op.type() == MEQ,
solverOperator),
new OperationSolver<>(false,
op -> op.type() == EQU || op.type() == NEQ,
solverOperator),
new OperationSolver<>(false,
op -> op.type() == AND || op.type() == IOR,
solverOperator));
public enum OperatorType {
ADD("+", (a, b) -> {
var n1 = tryNumber(a);
var n2 = tryNumber(b);
return n1 != null && n2 != null
? simplifyNumber(n1 + n2)
: a + b;
}),
SUB("-", (a, b) -> {
var n1 = tryNumber(a);
var n2 = tryNumber(b);
return n1 != null && n2 != null
? simplifyNumber(n1 - n2)
: a.replace(b, "");
}),
MUL("*", (a, b) -> {
var n1 = tryNumber(a);
var n2 = tryNumber(b);
return n1 != null && n2 != null
? simplifyNumber(n1 * n2)
: (n2 == null ? null : a.repeat(n2.intValue()));
}),
DIV("/", (a, b) -> {
var n1 = tryNumber(a);
var n2 = tryNumber(b);
return n1 != null && n2 != null
? simplifyNumber(n1 / n2)
: a.replace(b, "\n");
}),
MOD("%", (a, b) -> {
var n1 = tryNumber(a);
var n2 = tryNumber(b);
if (n1 != null && n2 != null)
return simplifyNumber(n1 % n2);
int pos = a.indexOf(b);
return pos < 0 ? a : a.substring(0, pos);
}),
POW("^", (a, b) -> {
var n1 = tryNumber(a);
var n2 = tryNumber(b);
return n1 != null && n2 != null
? simplifyNumber(Math.pow(n1, n2))
: null;
}),
LES("<", (a, b) -> {
var n1 = tryNumber(a);
var n2 = tryNumber(b);
return n1 != null && n2 != null
? (n1 < n2) + ""
: (a.compareTo(b) < 0) + "";
}),
LEQ("<=", (a, b) -> {
var n1 = tryNumber(a);
var n2 = tryNumber(b);
return n1 != null && n2 != null
? (n1 <= n2) + ""
: (a.compareTo(b) <= 0) + "";
}),
MOR(">", (a, b) -> {
var n1 = tryNumber(a);
var n2 = tryNumber(b);
return n1 != null && n2 != null
? (n1 > n2) + ""
: (a.compareTo(b) > 0) + "";
}),
MEQ(">=", (a, b) -> {
var n1 = tryNumber(a);
var n2 = tryNumber(b);
return n1 != null && n2 != null
? (n1 >= n2) + ""
: (a.compareTo(b) >= 0) + "";
}),
EQU("==", (a, b) -> {
var n1 = tryNumber(a);
var n2 = tryNumber(b);
return n1 != null && n2 != null
? (n1.doubleValue() == n2.doubleValue()) + ""
: a.equals(b) + "";
}),
NEQ("!=", (a, b) -> {
var n1 = tryNumber(a);
var n2 = tryNumber(b);
return n1 != null && n2 != null
? (n1.doubleValue() != n2.doubleValue()) + ""
: !a.equals(b) + "";
}),
AND("&", (a, b) -> (tryBoolean(a) && tryBoolean(b)) + ""),
IOR("|", (a, b) -> (tryBoolean(a) || tryBoolean(b)) + ""),
NOT("!", (a, b) -> !tryBoolean(a) + ""),
UMS("-", (a, b) -> {
var n1 = tryNumber(a);
return n1 != null ? -n1 + "" : "-" + a;
});
private final String operator;
private final BinaryOperator combiner;
OperatorType(String operator, BinaryOperator combiner) {
this.operator = operator;
this.combiner = combiner;
}
public String toString() {
return operator;
}
public static OperatorType from(String s) {
return Arrays.stream(values())
.filter(v -> v.operator.equals(s)
|| (v == EQU && s.replace("=", "").isEmpty())
|| (v == AND && s.replace("&", "").isEmpty())
|| (v == IOR && s.replace("|", "").isEmpty()))
.findFirst().orElse(null);
}
public String operate(String a, String b) {
return combiner.apply(a, b);
}
}
}