mirror of
https://github.com/Flowsqy/ShopChest.git
synced 2024-11-14 23:15:10 +01:00
Add base method for final parsing and reverse checking
This commit is contained in:
parent
b8fc15a6a8
commit
42f8ad4744
@ -0,0 +1,22 @@
|
||||
package de.epiceric.shopchest.config.hologram.condition;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ProviderCondition<P> implements Condition<P> {
|
||||
|
||||
private final Function<P, Boolean> booleanProvider;
|
||||
|
||||
public ProviderCondition(Function<P, Boolean> booleanProvider) {
|
||||
this.booleanProvider = booleanProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(P values) {
|
||||
return booleanProvider.apply(values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return booleanProvider.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package de.epiceric.shopchest.config.hologram.parser;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public class Chain<T> {
|
||||
|
||||
private Chain<T> before;
|
||||
private Chain<T> after;
|
||||
private T value;
|
||||
|
||||
public Chain(T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Chain(Chain<T> before, Chain<T> after, T value) {
|
||||
this.before = before;
|
||||
this.after = after;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static <T> Chain<T> getChain(Iterable<T> iterable) {
|
||||
Chain<T> first = null;
|
||||
Chain<T> previous = null;
|
||||
final Iterator<T> iterator = iterable.iterator();
|
||||
if (iterator.hasNext()) {
|
||||
first = previous = new Chain<>(iterator.next());
|
||||
}
|
||||
while (iterator.hasNext()) {
|
||||
final Chain<T> chain = new Chain<>(previous, null, iterator.next());
|
||||
previous.setAfter(chain);
|
||||
previous = chain;
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
public Chain<T> getBefore() {
|
||||
return before;
|
||||
}
|
||||
|
||||
public void setBefore(Chain<T> before) {
|
||||
this.before = before;
|
||||
}
|
||||
|
||||
public Chain<T> getAfter() {
|
||||
return after;
|
||||
}
|
||||
|
||||
public void setAfter(Chain<T> after) {
|
||||
this.after = after;
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
@ -1,9 +1,12 @@
|
||||
package de.epiceric.shopchest.config.hologram.parser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import de.epiceric.shopchest.config.hologram.condition.Condition;
|
||||
import de.epiceric.shopchest.config.hologram.condition.ProviderCondition;
|
||||
import de.epiceric.shopchest.config.hologram.condition.ReverseCondition;
|
||||
import de.epiceric.shopchest.config.hologram.provider.MapProvider;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class FormatParser {
|
||||
|
||||
@ -152,14 +155,15 @@ public class FormatParser {
|
||||
final Counter counter = new Counter();
|
||||
final List<Token<?>> resolvedTokens = resolveNode(tokenIterator, counter).getValue();
|
||||
if (counter.get() > 0) {
|
||||
// TODO create a custom exception
|
||||
throw new RuntimeException("Start unit '(' without closing it");
|
||||
} else if (counter.get() < 0) {
|
||||
// TODO create a custom exception
|
||||
throw new RuntimeException("End unit ')' without starting it");
|
||||
}
|
||||
return resolvedTokens;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Token<List<Token<?>>> resolveNode(Iterator<Token<?>> tokens, Counter counter) {
|
||||
final List<Token<?>> nodeTokens = new LinkedList<>();
|
||||
while (tokens.hasNext()) {
|
||||
@ -177,13 +181,97 @@ public class FormatParser {
|
||||
// TODO Create a custom exception
|
||||
throw new RuntimeException("Empty unit '( )'");
|
||||
}
|
||||
// Extract if there is useless parenthesis
|
||||
if (nodeTokens.size() == 1) {
|
||||
final Token<?> token = nodeTokens.get(0);
|
||||
if (token.getType() == Token.NODE) {
|
||||
return (Token<List<Token<?>>>) token;
|
||||
final Token<List<Token<?>>> typedToken = getTypedNoteToken(token);
|
||||
if (typedToken != null) {
|
||||
return typedToken;
|
||||
}
|
||||
}
|
||||
return new Token<>(Token.NODE, nodeTokens);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Token<List<Token<?>>> getTypedNoteToken(Token<?> token) {
|
||||
if (token.getType() == Token.NODE) {
|
||||
return (Token<List<Token<?>>>) token;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public <P> Token<?> createFunctions(Iterable<Token<?>> tokens, Function<String, P> providerFunction, Map<P, Class<?>> providerTypes) {
|
||||
Chain<Token<?>> tokensChain = Chain.getChain(tokens);
|
||||
|
||||
// Node
|
||||
Chain<Token<?>> nodeChain = tokensChain;
|
||||
while (nodeChain != null) {
|
||||
final Token<?> token = nodeChain.getValue();
|
||||
final Token<List<Token<?>>> typedToken = getTypedNoteToken(token);
|
||||
if (typedToken != null) {
|
||||
nodeChain.setValue(createFunctions(typedToken.getValue(), providerFunction, providerTypes));
|
||||
}
|
||||
nodeChain = nodeChain.getAfter();
|
||||
}
|
||||
|
||||
// Reverse
|
||||
Chain<Token<?>> reverseChain = tokensChain;
|
||||
while (reverseChain != null) {
|
||||
// Reverse check
|
||||
if (reverseChain.getValue().getType() == Token.REVERSE) {
|
||||
final Chain<Token<?>> nextChain = reverseChain.getAfter();
|
||||
// Next check
|
||||
if (nextChain == null) {
|
||||
// TODO Create custom exceptions
|
||||
throw new RuntimeException("Try to reverse a condition that does not exist");
|
||||
}
|
||||
final Token<?> nextToken = nextChain.getValue();
|
||||
|
||||
// Create reversed
|
||||
final Condition<?> reversed;
|
||||
final boolean isValue = nextToken.getType() == Token.VALUE;
|
||||
if (isValue || nextToken.getType() == Token.VALUE) {
|
||||
if (isValue) {
|
||||
final String value = (String) nextToken.getValue();
|
||||
final P provided = providerFunction.apply(value);
|
||||
// It uses a valid provided value
|
||||
if (provided != null) {
|
||||
final Class<?> providedClass = providerTypes.get(provided);
|
||||
// The provided value is a boolean
|
||||
if (providedClass == Boolean.class) {
|
||||
reversed = new ReverseCondition<>(new ProviderCondition<>(
|
||||
new MapProvider.BooleanMapProvider<>(provided)
|
||||
));
|
||||
} else {
|
||||
throw new RuntimeException("'" + value + "' can not be used as a boolean");
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("'" + value + "' does not exist");
|
||||
}
|
||||
}
|
||||
// It's a condition
|
||||
else {
|
||||
reversed = new ReverseCondition<>((Condition<?>) nextToken.getValue());
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Try to reverse something that does not represent a condition");
|
||||
}
|
||||
|
||||
// Set the chain
|
||||
final Chain<Token<?>> afterConditionChain = nextChain.getAfter();
|
||||
reverseChain.setValue(new Token<>(Token.CONDITION, reversed));
|
||||
if (afterConditionChain != null) {
|
||||
afterConditionChain.setBefore(reverseChain);
|
||||
reverseChain.setAfter(afterConditionChain);
|
||||
} else {
|
||||
reverseChain.setAfter(null);
|
||||
}
|
||||
}
|
||||
|
||||
reverseChain = reverseChain.getAfter();
|
||||
}
|
||||
|
||||
return tokensChain == null ? null : tokensChain.getValue();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
package de.epiceric.shopchest.config.hologram.parser;
|
||||
|
||||
import de.epiceric.shopchest.config.hologram.calculation.Calculation;
|
||||
import de.epiceric.shopchest.config.hologram.condition.Condition;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Token<T> {
|
||||
@ -14,6 +17,8 @@ public class Token<T> {
|
||||
public final static TokenType<LogicOperator> LOGIC_OPERATOR = new TokenType<>("Logic operator");
|
||||
public final static TokenType<CalculationOperator> CALCULATION_OPERATOR = new TokenType<>("Calculation operator");
|
||||
public final static TokenType<List<Token<?>>> NODE = new TokenType<>("Node");
|
||||
public final static TokenType<Calculation<?>> CALCULATION = new TokenType<>("Calculation");
|
||||
public final static TokenType<Condition<?>> CONDITION = new TokenType<>("Condition");
|
||||
private final TokenType<T> type;
|
||||
private final T value;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user