All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.diversionmc.d3.operation.Operator Maven / Gradle / Ivy

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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy