Restructured StringEquationParser -> Equation, basically swapping inner/outer class
This commit is contained in:
parent
bd030ec374
commit
fa93651cb8
6 changed files with 217 additions and 206 deletions
|
@ -21,7 +21,8 @@ import org.dimdev.dimdoors.pockets.modifier.Modifier;
|
|||
import org.dimdev.dimdoors.util.Location;
|
||||
import org.dimdev.dimdoors.util.PocketGenerationParameters;
|
||||
import org.dimdev.dimdoors.util.Weighted;
|
||||
import org.dimdev.dimdoors.util.math.StringEquationParser;
|
||||
import org.dimdev.dimdoors.util.math.Equation;
|
||||
import org.dimdev.dimdoors.util.math.Equation.EquationParseException;
|
||||
import org.dimdev.dimdoors.world.pocket.Pocket;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -39,7 +40,7 @@ public abstract class PocketGenerator implements Weighted<PocketGenerationParame
|
|||
private final List<Modifier> modifierList = new ArrayList<>();
|
||||
|
||||
private String weight;
|
||||
private StringEquationParser.Equation weightEquation;
|
||||
private Equation weightEquation;
|
||||
|
||||
public PocketGenerator() { }
|
||||
|
||||
|
@ -64,12 +65,12 @@ public abstract class PocketGenerator implements Weighted<PocketGenerationParame
|
|||
|
||||
private void parseWeight() {
|
||||
try {
|
||||
this.weightEquation = StringEquationParser.parse(weight);
|
||||
} catch (StringEquationParser.EquationParseException e) {
|
||||
this.weightEquation = Equation.parse(weight);
|
||||
} catch (EquationParseException e) {
|
||||
LOGGER.error("Could not parse weight equation \"" + weight + "\", defaulting to default weight equation \"" + defaultWeightEquation + "\"", e);
|
||||
try {
|
||||
this.weightEquation = StringEquationParser.parse(defaultWeightEquation);
|
||||
} catch (StringEquationParser.EquationParseException equationParseException) {
|
||||
this.weightEquation = Equation.parse(defaultWeightEquation);
|
||||
} catch (EquationParseException equationParseException) {
|
||||
LOGGER.error("Could not parse default weight equation \"" + defaultWeightEquation + "\", defaulting to fallback weight \"" + fallbackWeight + "\"", equationParseException);
|
||||
this.weightEquation = stringDoubleMap -> fallbackWeight;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,8 @@ import net.minecraft.nbt.CompoundTag;
|
|||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dimdev.dimdoors.util.PocketGenerationParameters;
|
||||
import org.dimdev.dimdoors.util.math.StringEquationParser;
|
||||
import org.dimdev.dimdoors.util.math.Equation;
|
||||
import org.dimdev.dimdoors.util.math.Equation.EquationParseException;
|
||||
import org.dimdev.dimdoors.world.level.DimensionalRegistry;
|
||||
import org.dimdev.dimdoors.world.pocket.Pocket;
|
||||
|
||||
|
@ -15,17 +16,17 @@ public class VoidGenerator extends PocketGenerator {
|
|||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
public static final String KEY = "void";
|
||||
private String width;
|
||||
private StringEquationParser.Equation heightEquation;
|
||||
private Equation heightEquation;
|
||||
private String height;
|
||||
private StringEquationParser.Equation widthEquation;
|
||||
private Equation widthEquation;
|
||||
private String length;
|
||||
private StringEquationParser.Equation lengthEquation;
|
||||
private Equation lengthEquation;
|
||||
private String offsetX;
|
||||
private StringEquationParser.Equation offsetXEquation;
|
||||
private Equation offsetXEquation;
|
||||
private String offsetY;
|
||||
private StringEquationParser.Equation offsetYEquation;
|
||||
private Equation offsetYEquation;
|
||||
private String offsetZ;
|
||||
private StringEquationParser.Equation offsetZEquation;
|
||||
private Equation offsetZEquation;
|
||||
|
||||
@Override
|
||||
public Pocket prepareAndPlacePocket(PocketGenerationParameters parameters) {
|
||||
|
@ -53,19 +54,19 @@ public class VoidGenerator extends PocketGenerator {
|
|||
|
||||
try {
|
||||
width = tag.getString("width");
|
||||
widthEquation = StringEquationParser.parse(width);
|
||||
widthEquation = Equation.parse(width);
|
||||
height = tag.getString("height");
|
||||
heightEquation = StringEquationParser.parse(height);
|
||||
heightEquation = Equation.parse(height);
|
||||
length = tag.getString("length");
|
||||
lengthEquation = StringEquationParser.parse(length);
|
||||
lengthEquation = Equation.parse(length);
|
||||
|
||||
offsetX = tag.contains("offset_x") ? tag.getString("offset_x") : "0";
|
||||
offsetXEquation = StringEquationParser.parse(offsetX);
|
||||
offsetXEquation = Equation.parse(offsetX);
|
||||
offsetY = tag.contains("offset_y") ? tag.getString("offset_y") : "0";
|
||||
offsetYEquation = StringEquationParser.parse(offsetY);
|
||||
offsetYEquation = Equation.parse(offsetY);
|
||||
offsetZ = tag.contains("offset_z") ? tag.getString("offset_z") : "0";
|
||||
offsetZEquation = StringEquationParser.parse(offsetZ);
|
||||
} catch (StringEquationParser.EquationParseException e) {
|
||||
offsetZEquation = Equation.parse(offsetZ);
|
||||
} catch (EquationParseException e) {
|
||||
LOGGER.error(e);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@ import org.dimdev.dimdoors.rift.registry.LinkProperties;
|
|||
import org.dimdev.dimdoors.rift.targets.PocketEntranceMarker;
|
||||
import org.dimdev.dimdoors.rift.targets.PocketExitMarker;
|
||||
import org.dimdev.dimdoors.util.PocketGenerationParameters;
|
||||
import org.dimdev.dimdoors.util.math.StringEquationParser;
|
||||
import org.dimdev.dimdoors.util.math.Equation;
|
||||
import org.dimdev.dimdoors.util.math.Equation.EquationParseException;
|
||||
import org.dimdev.dimdoors.world.pocket.Pocket;
|
||||
|
||||
public class DimensionalDoorModifier implements Modifier {
|
||||
|
@ -38,9 +39,9 @@ public class DimensionalDoorModifier implements Modifier {
|
|||
private String x;
|
||||
private String y;
|
||||
private String z;
|
||||
private StringEquationParser.Equation xEquation;
|
||||
private StringEquationParser.Equation yEquation;
|
||||
private StringEquationParser.Equation zEquation;
|
||||
private Equation xEquation;
|
||||
private Equation yEquation;
|
||||
private Equation zEquation;
|
||||
|
||||
|
||||
@Override
|
||||
|
@ -65,10 +66,10 @@ public class DimensionalDoorModifier implements Modifier {
|
|||
y = tag.getString("y");
|
||||
z = tag.getString("z");
|
||||
|
||||
xEquation = StringEquationParser.parse(x);
|
||||
yEquation = StringEquationParser.parse(y);
|
||||
zEquation = StringEquationParser.parse(z);
|
||||
} catch (StringEquationParser.EquationParseException e) {
|
||||
xEquation = Equation.parse(x);
|
||||
yEquation = Equation.parse(y);
|
||||
zEquation = Equation.parse(z);
|
||||
} catch (EquationParseException e) {
|
||||
LOGGER.error(e);
|
||||
}
|
||||
return this;
|
||||
|
|
|
@ -10,7 +10,8 @@ import org.dimdev.dimdoors.pockets.generator.PocketGenerator;
|
|||
import org.dimdev.dimdoors.pockets.modifier.Modifier;
|
||||
import org.dimdev.dimdoors.pockets.virtual.VirtualSingularPocket;
|
||||
import org.dimdev.dimdoors.util.PocketGenerationParameters;
|
||||
import org.dimdev.dimdoors.util.math.StringEquationParser;
|
||||
import org.dimdev.dimdoors.util.math.Equation;
|
||||
import org.dimdev.dimdoors.util.math.Equation.EquationParseException;
|
||||
import org.dimdev.dimdoors.world.pocket.Pocket;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -21,19 +22,19 @@ public abstract class PocketGeneratorReference extends VirtualSingularPocket {
|
|||
private static final int fallbackWeight = 5; // TODO: make config
|
||||
|
||||
private String weight;
|
||||
private StringEquationParser.Equation weightEquation;
|
||||
private Equation weightEquation;
|
||||
private Boolean setupLoot;
|
||||
private final List<Modifier> modifierList = Lists.newArrayList();
|
||||
|
||||
|
||||
private void parseWeight() {
|
||||
try {
|
||||
this.weightEquation = StringEquationParser.parse(weight);
|
||||
} catch (StringEquationParser.EquationParseException e) {
|
||||
this.weightEquation = Equation.parse(weight);
|
||||
} catch (EquationParseException e) {
|
||||
LOGGER.error("Could not parse weight equation \"" + weight + "\", defaulting to default weight equation \"" + defaultWeightEquation + "\"", e);
|
||||
try {
|
||||
this.weightEquation = StringEquationParser.parse(defaultWeightEquation);
|
||||
} catch (StringEquationParser.EquationParseException equationParseException) {
|
||||
this.weightEquation = Equation.parse(defaultWeightEquation);
|
||||
} catch (EquationParseException equationParseException) {
|
||||
LOGGER.error("Could not parse default weight equation \"" + defaultWeightEquation + "\", defaulting to fallback weight \"" + fallbackWeight + "\"", equationParseException);
|
||||
this.weightEquation = stringDoubleMap -> fallbackWeight;
|
||||
}
|
||||
|
|
179
src/main/java/org/dimdev/dimdoors/util/math/Equation.java
Normal file
179
src/main/java/org/dimdev/dimdoors/util/math/Equation.java
Normal file
|
@ -0,0 +1,179 @@
|
|||
package org.dimdev.dimdoors.util.math;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public interface Equation {
|
||||
|
||||
double apply(Map<String, Double> variableMap);
|
||||
|
||||
static Equation parse(String equationString) throws EquationParseException {
|
||||
return StringEquationParser.INSTANCE.parse(equationString);
|
||||
}
|
||||
|
||||
class StringEquationParser {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
public static StringEquationParser INSTANCE = new StringEquationParser();
|
||||
private final static List<EquationParser> parseRules = new ArrayList<>();
|
||||
|
||||
static {
|
||||
// Parenthesis
|
||||
parseRules.add(toParse -> {
|
||||
if (!toParse.startsWith("(") || !toParse.endsWith(")")) return Optional.empty();
|
||||
return Optional.of(Equation.parse(toParse.substring(1, toParse.length() - 1)));
|
||||
});
|
||||
|
||||
// try to parse as Double
|
||||
parseRules.add(toParse -> {
|
||||
try {
|
||||
Double result = Double.parseDouble(toParse);
|
||||
return Optional.of(stringDoubleMap -> result);
|
||||
} catch (NumberFormatException e) {
|
||||
return Optional.empty();
|
||||
}
|
||||
});
|
||||
|
||||
// +, -
|
||||
Map<String, TriFunction<Map<String, Double>, Equation, Equation, Double>> sumOperations = new HashMap<>();
|
||||
sumOperations.put("+", (stringDoubleMap, first, second) -> first.apply(stringDoubleMap) + second.apply(stringDoubleMap));
|
||||
sumOperations.put("-", (stringDoubleMap, first, second) -> first.apply(stringDoubleMap) - second.apply(stringDoubleMap));
|
||||
parseRules.add(new SplitterParser(sumOperations));
|
||||
|
||||
// *, /, %
|
||||
Map<String, TriFunction<Map<String, Double>, Equation, Equation, Double>> dotOperations = new HashMap<>();
|
||||
dotOperations.put("*", (stringDoubleMap, first, second) -> first.apply(stringDoubleMap) * second.apply(stringDoubleMap));
|
||||
dotOperations.put("/", (stringDoubleMap, first, second) -> first.apply(stringDoubleMap) / second.apply(stringDoubleMap));
|
||||
dotOperations.put("%", (stringDoubleMap, first, second) -> first.apply(stringDoubleMap) % second.apply(stringDoubleMap));
|
||||
parseRules.add(new SplitterParser(dotOperations));
|
||||
|
||||
// x^y
|
||||
Map<String, TriFunction<Map<String, Double>, Equation, Equation, Double>> exponentOperations = new HashMap<>();
|
||||
exponentOperations.put("^", (stringDoubleMap, first, second) -> Math.pow(first.apply(stringDoubleMap), second.apply(stringDoubleMap)));
|
||||
parseRules.add(new SplitterParser(exponentOperations));
|
||||
|
||||
// H with H(0) = 1: https://en.wikipedia.org/wiki/Heaviside_step_function
|
||||
parseRules.add(new FunctionParser("H", 1, 1, ((stringDoubleMap, equations) -> equations[0].apply(stringDoubleMap) >= 0 ? 1d : 0d)));
|
||||
|
||||
// floor
|
||||
parseRules.add(new FunctionParser("floor", 1, 1, ((stringDoubleMap, equations) -> Math.floor(equations[0].apply(stringDoubleMap)))));
|
||||
|
||||
// ceil
|
||||
parseRules.add(new FunctionParser("ceil", 1, 1, ((stringDoubleMap, equations) -> Math.ceil(equations[0].apply(stringDoubleMap)))));
|
||||
|
||||
// max
|
||||
parseRules.add(new FunctionParser("max", 2, -1, ((stringDoubleMap, equations) -> {
|
||||
Double max = equations[0].apply(stringDoubleMap);
|
||||
for (int i = 1; i < equations.length; i++) {
|
||||
max = Math.max(max, equations[i].apply(stringDoubleMap));
|
||||
}
|
||||
return max;
|
||||
})));
|
||||
|
||||
// min
|
||||
parseRules.add(new FunctionParser("min", 2, -1, ((stringDoubleMap, equations) -> {
|
||||
Double min = equations[0].apply(stringDoubleMap);
|
||||
for (int i = 1; i < equations.length; i++) {
|
||||
min = Math.min(min, equations[i].apply(stringDoubleMap));
|
||||
}
|
||||
return min;
|
||||
})));
|
||||
|
||||
// variable replacer
|
||||
parseRules.add(new VariableReplacer());
|
||||
}
|
||||
|
||||
public Equation parse(String equationString) throws EquationParseException {
|
||||
equationString = equationString.replaceAll("\\s", "");
|
||||
for (EquationParser parser : parseRules) {
|
||||
Optional<Equation> equation = parser.tryParse(equationString);
|
||||
if (equation.isPresent()) return equation.get();
|
||||
}
|
||||
throw new EquationParseException("\"" + equationString + "\" could not be parsed");
|
||||
}
|
||||
|
||||
|
||||
private interface EquationParser {
|
||||
Optional<Equation> tryParse(String toParse) throws EquationParseException;
|
||||
}
|
||||
|
||||
private static class VariableReplacer implements EquationParser {
|
||||
@Override
|
||||
public Optional<Equation> tryParse(String toParse) {
|
||||
if (!toParse.matches("[a-zA-Z_][a-zA-Z0-9_]*")) return Optional.empty();
|
||||
return Optional.of(stringDoubleMap -> {
|
||||
if (stringDoubleMap != null && stringDoubleMap.containsKey(toParse)) return stringDoubleMap.get(toParse);
|
||||
LOGGER.error("Variable \"" + toParse + "\" was not passed to equation! Returning 0 as fallback.");
|
||||
return 0d;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static class SplitterParser implements EquationParser {
|
||||
private final Map<String, TriFunction<Map<String, Double>, Equation, Equation, Double>> operations;
|
||||
|
||||
public SplitterParser(Map<String, TriFunction<Map<String, Double>, Equation, Equation, Double>> operations) {
|
||||
this.operations = operations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Equation> tryParse(String toParse) throws EquationParseException {
|
||||
int depth = 0;
|
||||
for (int i = toParse.length() - 1; i >= 1 ; i--) {
|
||||
String substring = toParse.substring(i);
|
||||
if (substring.startsWith(")")) depth++;
|
||||
else if (substring.startsWith("(")) depth--;
|
||||
for(String symbol : operations.keySet()) {
|
||||
if (substring.startsWith(symbol) && depth == 0) {
|
||||
final TriFunction<Map<String, Double>, Equation, Equation, Double> operation = operations.get(symbol);
|
||||
final Equation first = Equation.parse(toParse.substring(0,i));
|
||||
final Equation second = Equation.parse(toParse.substring(i+1));
|
||||
return Optional.of(stringDoubleMap -> operation.apply(stringDoubleMap, first, second));
|
||||
}
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private static class FunctionParser implements EquationParser {
|
||||
private final String functionString;
|
||||
private final int minArguments;
|
||||
private final int maxArguments;
|
||||
private final BiFunction<Map<String, Double>, Equation[], Double> function;
|
||||
|
||||
public FunctionParser(String functionString, int minArguments, int maxArguments, BiFunction<Map<String, Double>, Equation[], Double> function) {
|
||||
this.functionString = functionString + "(";
|
||||
this.minArguments = minArguments;
|
||||
this.maxArguments = maxArguments;
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Equation> tryParse(String toParse) throws EquationParseException {
|
||||
if (!toParse.startsWith(functionString) || !toParse.endsWith(")")) return Optional.empty();
|
||||
String[] arguments = toParse.substring(functionString.length(), toParse.length()-1).split(",");
|
||||
if (minArguments > arguments.length || (maxArguments < arguments.length && maxArguments != -1)) return Optional.empty();
|
||||
final Equation[] argumentEquations = new Equation[arguments.length];
|
||||
for (int i = 0; i < arguments.length; i++) {
|
||||
argumentEquations[i] = Equation.parse(arguments[i]);
|
||||
}
|
||||
return Optional.of(stringDoubleMap -> function.apply(stringDoubleMap, argumentEquations));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private interface TriFunction<T, U, V, R> {
|
||||
R apply(T t, U u, V v);
|
||||
}
|
||||
}
|
||||
|
||||
class EquationParseException extends Exception {
|
||||
public EquationParseException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,172 +0,0 @@
|
|||
package org.dimdev.dimdoors.util.math;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class StringEquationParser {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private final static List<EquationParser> parseRules = new ArrayList<>();
|
||||
static {
|
||||
// Parenthesis
|
||||
parseRules.add(toParse -> {
|
||||
if (!toParse.startsWith("(") || !toParse.endsWith(")")) return Optional.empty();
|
||||
return Optional.of(parse(toParse.substring(1, toParse.length() - 1)));
|
||||
});
|
||||
|
||||
// try to parse as Double
|
||||
parseRules.add(toParse -> {
|
||||
try {
|
||||
Double result = Double.parseDouble(toParse);
|
||||
return Optional.of(stringDoubleMap -> result);
|
||||
} catch (NumberFormatException e) {
|
||||
return Optional.empty();
|
||||
}
|
||||
});
|
||||
|
||||
// +, -
|
||||
Map<String, TriFunction<Map<String, Double>, Equation, Equation, Double>> sumOperations = new HashMap<>();
|
||||
sumOperations.put("+", (stringDoubleMap, first, second) -> first.apply(stringDoubleMap) + second.apply(stringDoubleMap));
|
||||
sumOperations.put("-", (stringDoubleMap, first, second) -> first.apply(stringDoubleMap) - second.apply(stringDoubleMap));
|
||||
parseRules.add(new SplitterParser(sumOperations));
|
||||
|
||||
// *, /, %
|
||||
Map<String, TriFunction<Map<String, Double>, Equation, Equation, Double>> dotOperations = new HashMap<>();
|
||||
dotOperations.put("*", (stringDoubleMap, first, second) -> first.apply(stringDoubleMap) * second.apply(stringDoubleMap));
|
||||
dotOperations.put("/", (stringDoubleMap, first, second) -> first.apply(stringDoubleMap) / second.apply(stringDoubleMap));
|
||||
dotOperations.put("%", (stringDoubleMap, first, second) -> first.apply(stringDoubleMap) % second.apply(stringDoubleMap));
|
||||
parseRules.add(new SplitterParser(dotOperations));
|
||||
|
||||
// x^y
|
||||
Map<String, TriFunction<Map<String, Double>, Equation, Equation, Double>> exponentOperations = new HashMap<>();
|
||||
exponentOperations.put("^", (stringDoubleMap, first, second) -> Math.pow(first.apply(stringDoubleMap), second.apply(stringDoubleMap)));
|
||||
parseRules.add(new SplitterParser(exponentOperations));
|
||||
|
||||
// H with H(0) = 1: https://en.wikipedia.org/wiki/Heaviside_step_function
|
||||
parseRules.add(new FunctionParser("H", 1, 1, ((stringDoubleMap, equations) -> equations[0].apply(stringDoubleMap) >= 0 ? 1d : 0d)));
|
||||
|
||||
// floor
|
||||
parseRules.add(new FunctionParser("floor", 1, 1, ((stringDoubleMap, equations) -> Math.floor(equations[0].apply(stringDoubleMap)))));
|
||||
|
||||
// ceil
|
||||
parseRules.add(new FunctionParser("ceil", 1, 1, ((stringDoubleMap, equations) -> Math.ceil(equations[0].apply(stringDoubleMap)))));
|
||||
|
||||
// max
|
||||
parseRules.add(new FunctionParser("max", 2, -1, ((stringDoubleMap, equations) -> {
|
||||
Double max = equations[0].apply(stringDoubleMap);
|
||||
for (int i = 1; i < equations.length; i++) {
|
||||
max = Math.max(max, equations[i].apply(stringDoubleMap));
|
||||
}
|
||||
return max;
|
||||
})));
|
||||
|
||||
// min
|
||||
parseRules.add(new FunctionParser("min", 2, -1, ((stringDoubleMap, equations) -> {
|
||||
Double min = equations[0].apply(stringDoubleMap);
|
||||
for (int i = 1; i < equations.length; i++) {
|
||||
min = Math.min(min, equations[i].apply(stringDoubleMap));
|
||||
}
|
||||
return min;
|
||||
})));
|
||||
|
||||
// variable replacer
|
||||
parseRules.add(new VariableReplacer());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static Equation parse(String equationString) throws EquationParseException {
|
||||
equationString = equationString.replaceAll("\\s","");
|
||||
for (EquationParser parser : parseRules) {
|
||||
Optional<Equation> equation = parser.tryParse(equationString);
|
||||
if (equation.isPresent()) return equation.get();
|
||||
}
|
||||
throw new EquationParseException("\"" + equationString + "\" could not be parsed");
|
||||
}
|
||||
|
||||
|
||||
public interface Equation {
|
||||
double apply(Map<String, Double> variableMap);
|
||||
}
|
||||
|
||||
private interface EquationParser {
|
||||
Optional<Equation> tryParse(String toParse) throws EquationParseException;
|
||||
}
|
||||
|
||||
private static class VariableReplacer implements EquationParser {
|
||||
@Override
|
||||
public Optional<Equation> tryParse(String toParse) {
|
||||
if (!toParse.matches("[a-zA-Z_][a-zA-Z0-9_]*")) return Optional.empty();
|
||||
return Optional.of(stringDoubleMap -> {
|
||||
if (stringDoubleMap != null && stringDoubleMap.containsKey(toParse)) return stringDoubleMap.get(toParse);
|
||||
LOGGER.error("Variable \"" + toParse + "\" was not passed to equation! Returning 0 as fallback.");
|
||||
return 0d;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static class SplitterParser implements EquationParser {
|
||||
private final Map<String, TriFunction<Map<String, Double>, Equation, Equation, Double>> operations;
|
||||
|
||||
public SplitterParser(Map<String, TriFunction<Map<String, Double>, Equation, Equation, Double>> operations) {
|
||||
this.operations = operations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Equation> tryParse(String toParse) throws EquationParseException {
|
||||
int depth = 0;
|
||||
for (int i = toParse.length() - 1; i >= 1 ; i--) {
|
||||
String substring = toParse.substring(i);
|
||||
if (substring.startsWith(")")) depth++;
|
||||
else if (substring.startsWith("(")) depth--;
|
||||
for(String symbol : operations.keySet()) {
|
||||
if (substring.startsWith(symbol) && depth == 0) {
|
||||
final TriFunction<Map<String, Double>, Equation, Equation, Double> operation = operations.get(symbol);
|
||||
final Equation first = parse(toParse.substring(0,i));
|
||||
final Equation second = parse(toParse.substring(i+1));
|
||||
return Optional.of(stringDoubleMap -> operation.apply(stringDoubleMap, first, second));
|
||||
}
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private static class FunctionParser implements EquationParser {
|
||||
private final String functionString;
|
||||
private final int minArguments;
|
||||
private final int maxArguments;
|
||||
private final BiFunction<Map<String, Double>, Equation[], Double> function;
|
||||
|
||||
public FunctionParser(String functionString, int minArguments, int maxArguments, BiFunction<Map<String, Double>, Equation[], Double> function) {
|
||||
this.functionString = functionString + "(";
|
||||
this.minArguments = minArguments;
|
||||
this.maxArguments = maxArguments;
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Equation> tryParse(String toParse) throws EquationParseException {
|
||||
if (!toParse.startsWith(functionString) || !toParse.endsWith(")")) return Optional.empty();
|
||||
String[] arguments = toParse.substring(functionString.length(), toParse.length()-1).split(",");
|
||||
if (minArguments > arguments.length || (maxArguments < arguments.length && maxArguments != -1)) return Optional.empty();
|
||||
final Equation[] argumentEquations = new Equation[arguments.length];
|
||||
for (int i = 0; i < arguments.length; i++) {
|
||||
argumentEquations[i] = parse(arguments[i]);
|
||||
}
|
||||
return Optional.of(stringDoubleMap -> function.apply(stringDoubleMap, argumentEquations));
|
||||
}
|
||||
}
|
||||
|
||||
public static class EquationParseException extends Exception {
|
||||
public EquationParseException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
private interface TriFunction<T, U, V, R> {
|
||||
R apply(T t, U u, V v);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue