summaryrefslogtreecommitdiff
path: root/BJC-Utils2/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'BJC-Utils2/src/main/java')
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java14
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java10
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/GenericHelp.java6
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/package-info.java1
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/components/package-info.java3
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/BoundLazyPair.java31
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/BoundListHolder.java26
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/Either.java61
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/HalfBoundLazyPair.java21
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/package-info.java3
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/funcutils/ListUtils.java11
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/graph/Graph.java2
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedConfigReader.java55
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedReaderPragmas.java17
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java46
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java16
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java5
17 files changed, 239 insertions, 89 deletions
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java
index 54d2fa0..7a38e9b 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java
@@ -1,7 +1,5 @@
package bjc.utils.cli;
-import org.eclipse.jdt.annotation.Nullable;
-
/**
* Generic command implementation
*
@@ -18,14 +16,14 @@ public class GenericCommand implements ICommand {
* Create a new generic command
*
* @param handler
- * The handler to use for the command
+ * The handler to use for the command
* @param description
- * The description of the command. May be null
+ * The description of the command. May be null
* @param help
- * The detailed help message for the command. May be null
+ * The detailed help message for the command. May be null
*/
- public GenericCommand(ICommandHandler handler, @Nullable String description,
- @Nullable String help) {
+ public GenericCommand(ICommandHandler handler, String description,
+ String help) {
if (handler == null) {
throw new NullPointerException(
"Command handler must not be null");
@@ -59,4 +57,4 @@ public class GenericCommand implements ICommand {
public boolean isAlias() {
return false;
}
-} \ No newline at end of file
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java
index 4aab8a4..b6c6ea4 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java
@@ -7,8 +7,6 @@ import java.util.function.Consumer;
import bjc.utils.funcdata.FunctionalMap;
import bjc.utils.funcdata.IMap;
-import org.eclipse.jdt.annotation.Nullable;
-
/**
* A general command mode, with a customizable set of commands
*
@@ -381,7 +379,7 @@ public class GenericCommandMode implements ICommandMode {
* The custom prompt for this mode, or null to disable the
* custom prompt
*/
- public void setCustomPrompt(@Nullable String prompt) {
+ public void setCustomPrompt( String prompt) {
customPrompt = prompt;
}
@@ -392,7 +390,7 @@ public class GenericCommandMode implements ICommandMode {
* The desired name of this mode, or null to use the default
* name
*/
- public void setModeName(@Nullable String name) {
+ public void setModeName( String name) {
modeName = name;
}
@@ -404,7 +402,7 @@ public class GenericCommandMode implements ICommandMode {
* on unknown commands
*/
public void setUnknownCommandHandler(
- @Nullable BiConsumer<String, String[]> handler) {
+ BiConsumer<String, String[]> handler) {
if (handler == null) {
throw new NullPointerException("Handler must not be null");
}
@@ -429,4 +427,4 @@ public class GenericCommandMode implements ICommandMode {
defaultHandlers.put("exit", buildExitCommand());
}
-} \ No newline at end of file
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericHelp.java b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericHelp.java
index 2e46202..f4095f3 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericHelp.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericHelp.java
@@ -1,7 +1,5 @@
package bjc.utils.cli;
-import org.eclipse.jdt.annotation.Nullable;
-
/**
* Generic implementation of a help topic
*
@@ -22,7 +20,7 @@ public class GenericHelp implements ICommandHelp {
* The description of this help topic, or null if this help
* topic doesn't have a more detailed description
*/
- public GenericHelp(String summary, @Nullable String description) {
+ public GenericHelp(String summary, String description) {
if (summary == null) {
throw new NullPointerException(
"Help summary must be non-null");
@@ -46,4 +44,4 @@ public class GenericHelp implements ICommandHelp {
return summary;
}
-} \ No newline at end of file
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/package-info.java b/BJC-Utils2/src/main/java/bjc/utils/cli/package-info.java
index 1bdfd14..012ccc0 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/package-info.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/package-info.java
@@ -4,5 +4,4 @@
* @author ben
*
*/
-@org.eclipse.jdt.annotation.NonNullByDefault
package bjc.utils.cli;
diff --git a/BJC-Utils2/src/main/java/bjc/utils/components/package-info.java b/BJC-Utils2/src/main/java/bjc/utils/components/package-info.java
index 14a852a..9f83fb0 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/components/package-info.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/components/package-info.java
@@ -4,5 +4,4 @@
* @author ben
*
*/
-@org.eclipse.jdt.annotation.NonNullByDefault
-package bjc.utils.components; \ No newline at end of file
+package bjc.utils.components;
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/BoundLazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/BoundLazyPair.java
index 2b3fb29..c7eb965 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/BoundLazyPair.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/BoundLazyPair.java
@@ -80,6 +80,10 @@ class BoundLazyPair<OldLeft, OldRight, NewLeft, NewRight>
@Override
public <BoundLeft> IPair<BoundLeft, NewRight> bindLeft(
Function<NewLeft, IPair<BoundLeft, NewRight>> leftBinder) {
+ if (leftBinder == null) {
+ throw new NullPointerException("Left binder must not be null");
+ }
+
Supplier<NewLeft> leftSupp = () -> {
IPair<NewLeft, NewRight> newPair = boundPair;
@@ -97,6 +101,11 @@ class BoundLazyPair<OldLeft, OldRight, NewLeft, NewRight>
@Override
public <BoundRight> IPair<NewLeft, BoundRight> bindRight(
Function<NewRight, IPair<NewLeft, BoundRight>> rightBinder) {
+ if (rightBinder == null) {
+ throw new NullPointerException(
+ "Right binder must not be null");
+ }
+
Supplier<NewRight> rightSupp = () -> {
IPair<NewLeft, NewRight> newPair = boundPair;
@@ -116,6 +125,16 @@ class BoundLazyPair<OldLeft, OldRight, NewLeft, NewRight>
IPair<OtherLeft, OtherRight> otherPair,
BiFunction<NewLeft, OtherLeft, CombinedLeft> leftCombiner,
BiFunction<NewRight, OtherRight, CombinedRight> rightCombiner) {
+ if (otherPair == null) {
+ throw new NullPointerException("Other pair must not be null");
+ } else if (leftCombiner == null) {
+ throw new NullPointerException(
+ "Left combiner must not be null");
+ } else if (rightCombiner == null) {
+ throw new NullPointerException(
+ "Right combiner must not be null");
+ }
+
return otherPair.bind((otherLeft, otherRight) -> {
return bind((leftVal, rightVal) -> {
return new LazyPair<>(
@@ -128,6 +147,10 @@ class BoundLazyPair<OldLeft, OldRight, NewLeft, NewRight>
@Override
public <NewLeftType> IPair<NewLeftType, NewRight> mapLeft(
Function<NewLeft, NewLeftType> mapper) {
+ if (mapper == null) {
+ throw new NullPointerException("Mapper must not be null");
+ }
+
Supplier<NewLeftType> leftSupp = () -> {
if (!pairBound) {
NewLeft leftVal = binder
@@ -156,6 +179,10 @@ class BoundLazyPair<OldLeft, OldRight, NewLeft, NewRight>
@Override
public <NewRightType> IPair<NewLeft, NewRightType> mapRight(
Function<NewRight, NewRightType> mapper) {
+ if (mapper == null) {
+ throw new NullPointerException("Mapper must not be null");
+ }
+
Supplier<NewLeft> leftSupp = () -> {
if (!pairBound) {
return binder
@@ -184,6 +211,10 @@ class BoundLazyPair<OldLeft, OldRight, NewLeft, NewRight>
@Override
public <MergedType> MergedType merge(
BiFunction<NewLeft, NewRight, MergedType> merger) {
+ if (merger == null) {
+ throw new NullPointerException("Merger must not be null");
+ }
+
if (!pairBound) {
boundPair = binder.apply(leftSupplier.get(),
rightSupplier.get());
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/BoundListHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/BoundListHolder.java
index fe47dcc..a967383 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/BoundListHolder.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/BoundListHolder.java
@@ -5,6 +5,9 @@ import java.util.function.UnaryOperator;
import bjc.utils.funcdata.IList;
+/*
+ * Holds a list, converted into a holder
+ */
class BoundListHolder<ContainedType> implements IHolder<ContainedType> {
private IList<IHolder<ContainedType>> heldHolders;
@@ -15,6 +18,10 @@ class BoundListHolder<ContainedType> implements IHolder<ContainedType> {
@Override
public <BoundType> IHolder<BoundType> bind(
Function<ContainedType, IHolder<BoundType>> binder) {
+ if (binder == null) {
+ throw new NullPointerException("Binder must not be null");
+ }
+
IList<IHolder<BoundType>> boundHolders = heldHolders
.map((containedHolder) -> {
return containedHolder.bind(binder);
@@ -26,6 +33,11 @@ class BoundListHolder<ContainedType> implements IHolder<ContainedType> {
@Override
public <NewType> Function<ContainedType, IHolder<NewType>> lift(
Function<ContainedType, NewType> func) {
+ if (func == null) {
+ throw new NullPointerException(
+ "Function to lift must not be null");
+ }
+
return (val) -> {
return new ListHolder<>(func.apply(val));
};
@@ -34,6 +46,10 @@ class BoundListHolder<ContainedType> implements IHolder<ContainedType> {
@Override
public <MappedType> IHolder<MappedType> map(
Function<ContainedType, MappedType> mapper) {
+ if (mapper == null) {
+ throw new NullPointerException("Mapper must not be null");
+ }
+
IList<IHolder<MappedType>> mappedHolders = heldHolders
.map((containedHolder) -> {
return containedHolder.map(mapper);
@@ -45,6 +61,10 @@ class BoundListHolder<ContainedType> implements IHolder<ContainedType> {
@Override
public IHolder<ContainedType> transform(
UnaryOperator<ContainedType> transformer) {
+ if (transformer == null) {
+ throw new NullPointerException("Transformer must not be null");
+ }
+
heldHolders.forEach((containedHolder) -> {
containedHolder.transform(transformer);
});
@@ -55,6 +75,10 @@ class BoundListHolder<ContainedType> implements IHolder<ContainedType> {
@Override
public <UnwrappedType> UnwrappedType unwrap(
Function<ContainedType, UnwrappedType> unwrapper) {
+ if (unwrapper == null) {
+ throw new NullPointerException("Unwrapper must not be null");
+ }
+
return heldHolders.randItem().unwrap(unwrapper);
}
-}
+} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Either.java b/BJC-Utils2/src/main/java/bjc/utils/data/Either.java
index aa38959..3ab4c00 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/Either.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/Either.java
@@ -26,9 +26,8 @@ public class Either<LeftType, RightType>
* The value to put on the left
* @return An either with the left side occupied
*/
- public static <LeftType,
- RightType> Either<LeftType, RightType> fromLeft(
- LeftType left) {
+ public static <LeftType, RightType> Either<LeftType, RightType> fromLeft(
+ LeftType left) {
return new Either<>(left, null);
}
@@ -43,9 +42,8 @@ public class Either<LeftType, RightType>
* The value to put on the right
* @return An either with the right side occupied
*/
- public static <LeftType,
- RightType> Either<LeftType, RightType> fromRight(
- RightType right) {
+ public static <LeftType, RightType> Either<LeftType, RightType> fromRight(
+ RightType right) {
return new Either<>(null, right);
}
@@ -55,7 +53,7 @@ public class Either<LeftType, RightType>
private boolean isLeft;
- private Either(LeftType left, RightType right) {
+ private Either( LeftType left, RightType right) {
if (left == null) {
rightVal = right;
} else {
@@ -67,14 +65,21 @@ public class Either<LeftType, RightType>
@Override
public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind(
- BiFunction<LeftType, RightType,
- IPair<BoundLeft, BoundRight>> binder) {
+ BiFunction<LeftType, RightType, IPair<BoundLeft, BoundRight>> binder) {
+ if (binder == null) {
+ throw new NullPointerException("Binder must not be null");
+ }
+
return binder.apply(leftVal, rightVal);
}
@Override
public <BoundLeft> IPair<BoundLeft, RightType> bindLeft(
Function<LeftType, IPair<BoundLeft, RightType>> leftBinder) {
+ if (leftBinder == null) {
+ throw new NullPointerException("Left binder must not be null");
+ }
+
if (isLeft) {
return leftBinder.apply(leftVal);
}
@@ -85,6 +90,11 @@ public class Either<LeftType, RightType>
@Override
public <BoundRight> IPair<LeftType, BoundRight> bindRight(
Function<RightType, IPair<LeftType, BoundRight>> rightBinder) {
+ if (rightBinder == null) {
+ throw new NullPointerException(
+ "Right binder must not be null");
+ }
+
if (isLeft) {
return new Either<>(leftVal, null);
}
@@ -93,13 +103,20 @@ public class Either<LeftType, RightType>
}
@Override
- public <OtherLeft, OtherRight, CombinedLeft,
- CombinedRight> IPair<CombinedLeft, CombinedRight> combine(
- IPair<OtherLeft, OtherRight> otherPair,
- BiFunction<LeftType, OtherLeft,
- CombinedLeft> leftCombiner,
- BiFunction<RightType, OtherRight,
- CombinedRight> rightCombiner) {
+ public <OtherLeft, OtherRight, CombinedLeft, CombinedRight> IPair<CombinedLeft, CombinedRight> combine(
+ IPair<OtherLeft, OtherRight> otherPair,
+ BiFunction<LeftType, OtherLeft, CombinedLeft> leftCombiner,
+ BiFunction<RightType, OtherRight, CombinedRight> rightCombiner) {
+ if (otherPair == null) {
+ throw new NullPointerException("Other pair must not be null");
+ } else if (leftCombiner == null) {
+ throw new NullPointerException(
+ "Left combiner must not be null");
+ } else if (rightCombiner == null) {
+ throw new NullPointerException(
+ "Right combiner must not be null");
+ }
+
if (isLeft) {
return otherPair.bind((otherLeft, otherRight) -> {
return new Either<>(leftCombiner.apply(leftVal, otherLeft),
@@ -116,6 +133,10 @@ public class Either<LeftType, RightType>
@Override
public <NewLeft> IPair<NewLeft, RightType> mapLeft(
Function<LeftType, NewLeft> mapper) {
+ if (mapper == null) {
+ throw new NullPointerException("Mapper must not be null");
+ }
+
if (isLeft) {
return new Either<>(mapper.apply(leftVal), null);
}
@@ -126,6 +147,10 @@ public class Either<LeftType, RightType>
@Override
public <NewRight> IPair<LeftType, NewRight> mapRight(
Function<RightType, NewRight> mapper) {
+ if (mapper == null) {
+ throw new NullPointerException("Mapper must not be null");
+ }
+
if (isLeft) {
return new Either<>(leftVal, null);
}
@@ -136,6 +161,10 @@ public class Either<LeftType, RightType>
@Override
public <MergedType> MergedType merge(
BiFunction<LeftType, RightType, MergedType> merger) {
+ if (merger == null) {
+ throw new NullPointerException("Merger must not be null");
+ }
+
return merger.apply(leftVal, rightVal);
}
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/HalfBoundLazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/HalfBoundLazyPair.java
index 72c0bdf..58c375b 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/HalfBoundLazyPair.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/HalfBoundLazyPair.java
@@ -4,6 +4,9 @@ import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
+/*
+ * A lazy pair, with only one side bound
+ */
class HalfBoundLazyPair<OldType, NewLeft, NewRight>
implements IPair<NewLeft, NewRight> {
private Supplier<OldType> oldSupplier;
@@ -21,10 +24,9 @@ class HalfBoundLazyPair<OldType, NewLeft, NewRight>
@Override
public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind(
- BiFunction<NewLeft, NewRight,
- IPair<BoundLeft, BoundRight>> bindr) {
- IHolder<IPair<NewLeft,
- NewRight>> newPair = new Identity<>(boundPair);
+ BiFunction<NewLeft, NewRight, IPair<BoundLeft, BoundRight>> bindr) {
+ IHolder<IPair<NewLeft, NewRight>> newPair = new Identity<>(
+ boundPair);
IHolder<Boolean> newPairMade = new Identity<>(pairBound);
Supplier<NewLeft> leftSupp = () -> {
@@ -81,13 +83,10 @@ class HalfBoundLazyPair<OldType, NewLeft, NewRight>
}
@Override
- public <OtherLeft, OtherRight, CombinedLeft,
- CombinedRight> IPair<CombinedLeft, CombinedRight> combine(
- IPair<OtherLeft, OtherRight> otherPair,
- BiFunction<NewLeft, OtherLeft,
- CombinedLeft> leftCombiner,
- BiFunction<NewRight, OtherRight,
- CombinedRight> rightCombiner) {
+ public <OtherLeft, OtherRight, CombinedLeft, CombinedRight> IPair<CombinedLeft, CombinedRight> combine(
+ IPair<OtherLeft, OtherRight> otherPair,
+ BiFunction<NewLeft, OtherLeft, CombinedLeft> leftCombiner,
+ BiFunction<NewRight, OtherRight, CombinedRight> rightCombiner) {
return otherPair.bind((otherLeft, otherRight) -> {
return bind((leftVal, rightVal) -> {
return new LazyPair<>(
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/package-info.java b/BJC-Utils2/src/main/java/bjc/utils/data/package-info.java
index f5039bc..7b97a72 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/package-info.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/package-info.java
@@ -4,5 +4,4 @@
* @author ben
*
*/
-@org.eclipse.jdt.annotation.NonNullByDefault
-package bjc.utils.data; \ No newline at end of file
+package bjc.utils.data;
diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/ListUtils.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/ListUtils.java
index 3b03406..cafa80f 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/ListUtils.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/funcutils/ListUtils.java
@@ -90,10 +90,13 @@ public class ListUtils {
IHolder<IList<String>> returnedList = new Identity<>(input);
- operators.forEach((operator) -> returnedList
- .transform((oldReturn) -> oldReturn.flatMap((token) -> {
+ operators.forEach((operator) -> {
+ returnedList.transform((oldReturn) -> {
+ return oldReturn.flatMap((token) -> {
return operator.merge(new TokenDeaffixer(token));
- })));
+ });
+ });
+ });
return returnedList.unwrap((list) -> list);
}
@@ -339,4 +342,4 @@ public class ListUtils {
return returnedList.getValue();
}
-} \ No newline at end of file
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/graph/Graph.java b/BJC-Utils2/src/main/java/bjc/utils/graph/Graph.java
index 798d20d..68d0ef1 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/graph/Graph.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/graph/Graph.java
@@ -286,4 +286,4 @@ public class Graph<T> {
return adjacencyMap;
}
-}
+} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedConfigReader.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedConfigReader.java
index 1ee19f5..9da76f8 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedConfigReader.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedConfigReader.java
@@ -26,13 +26,21 @@ import bjc.utils.funcdata.IMap;
*
*/
public class RuleBasedConfigReader<E> {
+ // Function to execute when starting a rule
+ // Takes the tokenizer, and a pair of the read token and application state
private BiConsumer<FunctionalStringTokenizer, IPair<String,
E>> startRule;
+ // Function to use when continuing a rule
+ // Takes a tokenizer and application state
private BiConsumer<FunctionalStringTokenizer,
E> continueRule;
+ // Function to use when ending a rule
+ // Takes an application state
private Consumer<
E> endRule;
+ // Map of pragma names to pragma actions
+ // Pragma actions are functions taking a tokenizer and application state
private IMap<String, BiConsumer<FunctionalStringTokenizer,
E>> pragmas;
@@ -79,36 +87,37 @@ public class RuleBasedConfigReader<E> {
}
private void continueRule(E state, boolean ruleOpen, String line) {
+ // Make sure our input is correct
if (ruleOpen == false) {
throw new InputMismatchException(
"Can't continue rule with no rule currently open");
- }
-
- if (continueRule == null) {
+ } else if (continueRule == null) {
throw new InputMismatchException(
"Attempted to continue rule with rule continuation disabled."
+ " Check for extraneous tabs");
}
+ // Accept the rule
continueRule.accept(
new FunctionalStringTokenizer(line.substring(1), " "),
state);
- }
+ }
private boolean endRule(E state, boolean ruleOpen) {
+ // Ignore blank line without an open rule
if (ruleOpen == false) {
- // Ignore blank line without an open rule
+ // Do nothing
+ return false;
} else {
- if (endRule == null) {
- // Nothing happens on rule end
- ruleOpen = false;
- } else {
+ // Nothing happens on rule end
+ if (endRule != null) {
+ // Process the rule ending
endRule.accept(state);
}
- ruleOpen = false;
+ // Return a closed rule
+ return false;
}
- return ruleOpen;
}
/**
@@ -126,30 +135,35 @@ public class RuleBasedConfigReader<E> {
"Input stream must not be null");
}
- E state;
+ // Application state: We're giving this back later
+ E state = initialState;
+ // Prepare our input source
try (Scanner inputSource = new Scanner(inputStream, "\n")) {
-
- state = initialState;
+ // This is true when a rule's open
IHolder<Boolean> ruleOpen = new Identity<>(false);
+ // Do something for every line of the file
inputSource.forEachRemaining((line) -> {
+ // Skip comment lines
if (line.startsWith("#") || line.startsWith("//")) {
// It's a comment
return;
} else if (line.equals("")) {
+ // End the rule
ruleOpen.replace(endRule(state, ruleOpen.getValue()));
-
- return;
} else if (line.startsWith("\t")) {
+ // Continue the rule
continueRule(state, ruleOpen.getValue(), line);
} else {
+ // Open a rule
ruleOpen.replace(
startRule(state, ruleOpen.getValue(), line));
}
});
}
+ // Return the state that the user has created
return state;
}
@@ -192,28 +206,37 @@ public class RuleBasedConfigReader<E> {
}
private boolean startRule(E state, boolean ruleOpen, String line) {
+ // Create the line tokenizer
FunctionalStringTokenizer tokenizer = new FunctionalStringTokenizer(
line, " ");
+ // Get the initial token
String nextToken = tokenizer.nextToken();
+ // Handle pragmas
if (nextToken.equals("pragma")) {
+ // Get the pragma name
String token = tokenizer.nextToken();
+ // Handle pragmas
pragmas.getOrDefault(token, (tokenzer, stat) -> {
throw new UnknownPragmaException(
"Unknown pragma " + token);
}).accept(tokenizer, state);
} else {
+ // Make sure input is correct
if (ruleOpen == true) {
throw new InputMismatchException("Attempted to open a"
+ " rule with a rule already open. Make sure rules are"
+ " seperated by blank lines");
}
+ // Start a rule
startRule.accept(tokenizer, new Pair<>(nextToken, state));
+
ruleOpen = true;
}
+
return ruleOpen;
}
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedReaderPragmas.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedReaderPragmas.java
index 392a6c8..eef55a8 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedReaderPragmas.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedReaderPragmas.java
@@ -29,19 +29,23 @@ public class RuleBasedReaderPragmas {
StateType> buildInteger(String name,
BiConsumer<Integer, StateType> consumer) {
return (tokenizer, state) -> {
+ // Check our input is correct
if (!tokenizer.hasMoreTokens()) {
throw new PragmaFormatException("Pragma " + name
+ " requires one integer argument");
}
+ // Read the argument
String token = tokenizer.nextToken();
try {
+ // Run the pragma
consumer.accept(Integer.parseInt(token), state);
} catch (NumberFormatException nfex) {
+ // Tell the user their argument isn't correct
PragmaFormatException pfex = new PragmaFormatException(
"Argument " + token
- + " to version pragma isn't a valid integer. "
+ + " to " + name + " pragma isn't a valid integer. "
+ "This pragma requires a integer argument");
pfex.initCause(nfex);
@@ -67,14 +71,17 @@ public class RuleBasedReaderPragmas {
StateType> buildStringCollapser(String name,
BiConsumer<String, StateType> consumer) {
return (tokenizer, state) -> {
+ // Check our input
if (!tokenizer.hasMoreTokens()) {
throw new PragmaFormatException("Pragma " + name
- + " requires one string argument");
+ + " requires one or more string arguments");
}
- consumer.accept(ListUtils.collapseTokens(
- tokenizer.toList((strang) -> strang)), state);
+ // Build our argument
+ String collapsed = ListUtils.collapseTokens(tokenizer.toList());
+
+ // Run the pragma
+ consumer.accept(collapsed, state);
};
}
-
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java
index c1cd5c7..99e3e60 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java
@@ -76,12 +76,15 @@ public class ShuntingYard<TokenType> {
@Override
public void accept(String token) {
+ // Handle operators
if (operators.containsKey(token)) {
+ // Pop operators while there isn't a higher precedence one
while (!stack.isEmpty()
&& isHigherPrec(token, stack.peek())) {
output.add(transform.apply(stack.pop()));
}
+ // Put this operator onto the stack
stack.push(token);
} else if (StringUtils.containsOnly(token, "\\(")) {
// Handle groups of parenthesis for multiple nesting levels
@@ -90,12 +93,15 @@ public class ShuntingYard<TokenType> {
// Handle groups of parenthesis for multiple nesting levels
String swappedToken = token.replace(')', '(');
+ // Remove tokens up to a matching parenthesis
while (!stack.peek().equals(swappedToken)) {
output.add(transform.apply(stack.pop()));
}
+ // Remove the parenthesis
stack.pop();
} else {
+ // Just add the transformed token
output.add(transform.apply(token));
}
}
@@ -115,6 +121,7 @@ public class ShuntingYard<TokenType> {
public ShuntingYard(boolean configureBasics) {
operators = new FunctionalMap<>();
+ // Add basic operators if we're configured to do so
if (configureBasics) {
operators.put("+", Operator.ADD);
operators.put("-", Operator.SUBTRACT);
@@ -132,8 +139,10 @@ public class ShuntingYard<TokenType> {
* The precedence of the operator to add
*/
public void addOp(String operatorToken, int precedence) {
- this.addOp(operatorToken,
- IPrecedent.newSimplePrecedent(precedence));
+ // Create the precedence marker
+ IPrecedent prec = IPrecedent.newSimplePrecedent(precedence);
+
+ this.addOp(operatorToken, prec);
}
/**
@@ -145,24 +154,31 @@ public class ShuntingYard<TokenType> {
* The precedence of the operator
*/
public void addOp(String operatorToken, IPrecedent precedence) {
+ // Complain about trying to add an incorrect operator
if (operatorToken == null) {
throw new NullPointerException("Operator must not be null");
+ } else if(precedence == null) {
+ throw new NullPointerException("Precedence must not be null");
}
+ // Add the operator to the ones we handle
operators.put(operatorToken, precedence);
}
- private boolean isHigherPrec(String leftOperator,
- String rightOperator) {
+ private boolean isHigherPrec(String leftOperator, String rightOperator) {
+ // Check if the right operator exists
boolean operatorExists = operators.containsKey(rightOperator);
+ // If it doesn't, the left is higher precedence.
if (!operatorExists) {
return false;
}
+ // Get the precedence of operators
int rightPrecedence = operators.get(rightOperator).getPrecedence();
int leftPrecedence = operators.get(leftOperator).getPrecedence();
+ // Evaluate what we were asked
return rightPrecedence >= leftPrecedence;
}
@@ -177,20 +193,26 @@ public class ShuntingYard<TokenType> {
*/
public IList<TokenType> postfix(IList<String> input,
Function<String, TokenType> tokenTransformer) {
+ // Check our input
if (input == null) {
throw new NullPointerException("Input must not be null");
} else if (tokenTransformer == null) {
throw new NullPointerException("Transformer must not be null");
}
+ // Here's what we're handing back
IList<TokenType> output = new FunctionalList<>();
+ // The stack to put operators on
Deque<String> stack = new LinkedList<>();
+ // Shunt the tokens
input.forEach(new TokenShunter(output, stack, tokenTransformer));
- stack.forEach(
- (token) -> output.add(tokenTransformer.apply(token)));
+ // Transform any resulting tokens
+ stack.forEach((token) -> {
+ output.add(tokenTransformer.apply(token));
+ });
return output;
}
@@ -199,13 +221,15 @@ public class ShuntingYard<TokenType> {
* Remove an operator from the list of shuntable operators
*
* @param token
- * The token representing the operator
+ * The token representing the operator. If null, remove all
+ * operators
*/
public void removeOp(String token) {
+ // Check if we want to remove all operators
if (token == null) {
- throw new NullPointerException("Token must not be null");
+ operators = new FunctionalMap<>();
+ } else {
+ operators.remove(token);
}
-
- operators.remove(token);
}
-} \ No newline at end of file
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java
index 149cbbf..ff3a6b9 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java
@@ -13,6 +13,7 @@ import bjc.utils.data.Pair;
import bjc.utils.data.Tree;
final class TokenTransformer<TokenType> implements Consumer<TokenType> {
+ // Handle operators
private final class OperatorHandler implements UnaryOperator<
IPair<Deque<ITree<TokenType>>, ITree<TokenType>>> {
private TokenType element;
@@ -24,6 +25,7 @@ final class TokenTransformer<TokenType> implements Consumer<TokenType> {
@Override
public IPair<Deque<ITree<TokenType>>, ITree<TokenType>> apply(
IPair<Deque<ITree<TokenType>>, ITree<TokenType>> pair) {
+ // Replace the current AST with the result of handling an operator
return pair.bindLeft((queuedASTs) -> {
return handleOperator(queuedASTs);
});
@@ -32,12 +34,15 @@ final class TokenTransformer<TokenType> implements Consumer<TokenType> {
private IPair<Deque<ITree<TokenType>>,
ITree<TokenType>> handleOperator(
Deque<ITree<TokenType>> queuedASTs) {
+ // The AST we're going to hand back
ITree<TokenType> newAST;
+ // Handle special operators
if (isSpecialOperator.test(element)) {
newAST = handleSpecialOperator.apply(element)
.apply(queuedASTs);
} else {
+ // Error if we don't have enough for a binary operator
if (queuedASTs.size() < 2) {
throw new IllegalStateException(
"Attempted to parse binary operator without enough operands.\n"
@@ -46,14 +51,18 @@ final class TokenTransformer<TokenType> implements Consumer<TokenType> {
+ queuedASTs.peek());
}
+ // Grab the two operands
ITree<TokenType> rightAST = queuedASTs.pop();
ITree<TokenType> leftAST = queuedASTs.pop();
+ // Create a new AST
newAST = new Tree<>(element, leftAST, rightAST);
}
+ // Stick it onto the stack
queuedASTs.push(newAST);
+ // Hand back the state
return new Pair<>(queuedASTs, newAST);
}
}
@@ -69,6 +78,7 @@ final class TokenTransformer<TokenType> implements Consumer<TokenType> {
private Function<TokenType, Function<Deque<ITree<TokenType>>,
ITree<TokenType>>> handleSpecialOperator;
+ // Create a new transformer
public TokenTransformer(
IHolder<IPair<Deque<ITree<TokenType>>,
ITree<TokenType>>> initialState,
@@ -84,12 +94,16 @@ final class TokenTransformer<TokenType> implements Consumer<TokenType> {
@Override
public void accept(TokenType element) {
+ // Handle operators
if (operatorPredicate.test(element)) {
initialState.transform(new OperatorHandler(element));
} else {
ITree<TokenType> newAST = new Tree<>(element);
+ // Insert the new tree into the AST
initialState.transform((pair) -> {
+ // Transform the pair, ignoring the current AST in favor of the
+ // one consisting of the current element
return pair.bindLeft((queue) -> {
queue.push(newAST);
@@ -98,4 +112,4 @@ final class TokenTransformer<TokenType> implements Consumer<TokenType> {
});
}
}
-} \ No newline at end of file
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java
index 2ddde9d..0b61363 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java
@@ -36,6 +36,7 @@ public class TreeConstructor {
public static <TokenType> ITree<TokenType> constructTree(
IList<TokenType> tokens,
Predicate<TokenType> operatorPredicate) {
+ // Construct a tree with no special operators
return constructTree(tokens, operatorPredicate, (op) -> false,
null);
}
@@ -70,6 +71,7 @@ public class TreeConstructor {
Predicate<TokenType> isSpecialOperator,
Function<TokenType, Function<Deque<ITree<TokenType>>,
ITree<TokenType>>> handleSpecialOperator) {
+ // Make sure our parameters are valid
if (tokens == null) {
throw new NullPointerException("Tokens must not be null");
} else if (operatorPredicate == null) {
@@ -80,14 +82,17 @@ public class TreeConstructor {
"Special operator determiner must not be null");
}
+ // Here is the state for the tree construction
IHolder<IPair<Deque<ITree<TokenType>>,
ITree<TokenType>>> initialState = new Identity<>(
new Pair<>(new LinkedList<>(), null));
+ // Transform each of the tokens
tokens.forEach(
new TokenTransformer<>(initialState, operatorPredicate,
isSpecialOperator, handleSpecialOperator));
+ // Grab the tree from the state
return initialState.unwrap((pair) -> {
return pair.getRight();
});