summaryrefslogtreecommitdiff
path: root/base/src/main/java/bjc/utils/patterns
diff options
context:
space:
mode:
Diffstat (limited to 'base/src/main/java/bjc/utils/patterns')
-rw-r--r--base/src/main/java/bjc/utils/patterns/ComplexPattern.java98
-rw-r--r--base/src/main/java/bjc/utils/patterns/FunctionalPattern.java6
-rw-r--r--base/src/main/java/bjc/utils/patterns/FunctionalPatternMatcher.java2
-rw-r--r--base/src/main/java/bjc/utils/patterns/IPatternMatcher.java85
-rw-r--r--base/src/main/java/bjc/utils/patterns/MutablePatternMatcher.java15
-rw-r--r--base/src/main/java/bjc/utils/patterns/Pattern.java6
-rw-r--r--base/src/main/java/bjc/utils/patterns/PatternMatcher.java96
-rw-r--r--base/src/main/java/bjc/utils/patterns/SimplePatternMatcher.java41
-rw-r--r--base/src/main/java/bjc/utils/patterns/SimplePatttern.java4
9 files changed, 194 insertions, 159 deletions
diff --git a/base/src/main/java/bjc/utils/patterns/ComplexPattern.java b/base/src/main/java/bjc/utils/patterns/ComplexPattern.java
index 3926f2c..c6d72ec 100644
--- a/base/src/main/java/bjc/utils/patterns/ComplexPattern.java
+++ b/base/src/main/java/bjc/utils/patterns/ComplexPattern.java
@@ -23,7 +23,7 @@ public interface ComplexPattern<ReturnType, PredType, InputType> {
* @return Whether or not this pattern is matched, as well as a state value
* that will get passed to the pattern if it did match.
*/
- IPair<Boolean, PredType> matches(InputType input);
+ Pair<Boolean, PredType> matches(InputType input);
/**
* Apply this pattern, once it has matched.
@@ -35,6 +35,8 @@ public interface ComplexPattern<ReturnType, PredType, InputType> {
*/
ReturnType apply(InputType input, PredType state);
+ /* Pattern producing functions */
+
/**
* Create a pattern composed from a predicate & a function.
*
@@ -48,8 +50,9 @@ public interface ComplexPattern<ReturnType, PredType, InputType> {
* @return A pattern composed from the passed in functions.
*/
static <RetType, PreType, InpType> ComplexPattern<RetType, PreType, InpType> from(
- Function<InpType, IPair<Boolean, PreType>> matcher,
- BiFunction<InpType, PreType, RetType> accepter) {
+ Function<InpType, Pair<Boolean, PreType>> matcher,
+ BiFunction<InpType, PreType, RetType> accepter)
+ {
return new FunctionalPattern<>(matcher, accepter);
}
@@ -68,9 +71,10 @@ public interface ComplexPattern<ReturnType, PredType, InputType> {
@SuppressWarnings("unchecked")
static <ClassType, RetType, InpType> ComplexPattern<RetType, ?, InpType> ofClass(
Class<ClassType> clasz,
- Function<ClassType, RetType> action) {
+ Function<ClassType, RetType> action)
+ {
return from(
- (input) -> IPair.pair(clasz.isInstance(input), null),
+ (input) -> Pair.pair(clasz.isInstance(input), null),
(input, ignored) -> action.apply((ClassType)input)
);
}
@@ -89,11 +93,12 @@ public interface ComplexPattern<ReturnType, PredType, InputType> {
static <RetType, InpType> ComplexPattern<RetType, ?, InpType> matchesObject(
InpType obj,
Function<InpType, RetType> action
- ) {
+ )
+ {
return from(
- (input) -> IPair.pair(obj.equals(input), null),
- (input, ignored) -> action.apply(input)
- );
+ (input) -> Pair.pair(obj.equals(input), null),
+ (input, ignored) -> action.apply(input)
+ );
}
/**
@@ -113,13 +118,16 @@ public interface ComplexPattern<ReturnType, PredType, InputType> {
static <RetType, InpType> ComplexPattern<RetType, ?, InpType> equalsString(
String pattern,
BiFunction<InpType, String, RetType> action
- ) {
+ )
+ {
+ Function<InpType, Pair<Boolean, String>> matcher = (input) -> {
+ String objString = input.toString();
+
+ return Pair.pair(pattern.equals(objString), objString);
+ };
+
return from(
- (input) -> {
- String objString = input.toString();
-
- return IPair.pair(pattern.equals(objString), objString);
- },
+ matcher,
(input, objString) -> action.apply(input, objString)
);
}
@@ -140,21 +148,21 @@ public interface ComplexPattern<ReturnType, PredType, InputType> {
String regex,
Predicate<Matcher> cond,
BiFunction<InpType, Matcher, RetType> action
- ) {
+ )
+ {
java.util.regex.Pattern regexPat = java.util.regex.Pattern.compile(regex);
+ Function<InpType, Pair<Boolean, Matcher>> matcher = (input) -> {
+ String inpString = input.toString();
+
+ Matcher mat = regexPat.matcher(inpString);
+
+ if (cond.test(mat)) return Pair.pair(true, mat);
+ else return Pair.pair(false, null);
+ };
+
return from(
- (input) -> {
- String inpString = input.toString();
-
- Matcher mat = regexPat.matcher(inpString);
-
- if (cond.test(mat)) {
- return IPair.pair(true, mat);
- } else {
- return IPair.pair(false, null);
- }
- },
+ matcher,
(input, res) -> action.apply(input, res)
);
}
@@ -162,6 +170,7 @@ public interface ComplexPattern<ReturnType, PredType, InputType> {
// @TODO Nov 21, 2020 Ben Culkin :MorePatterns
// Try and write something to iterate over Iterator in a type-safe manner
// Also, something for doing a sub-pattern match
+
/**
* Create a pattern which will always execute.
*
@@ -174,10 +183,41 @@ public interface ComplexPattern<ReturnType, PredType, InputType> {
*/
static <RetType, InpType> ComplexPattern<RetType, ?, InpType> otherwise(
Function<InpType, RetType> action
- ) {
+ )
+ {
return from(
- (input) -> IPair.pair(true, null),
+ (input) -> Pair.pair(true, null),
(input, ignored) -> action.apply(input)
);
}
+
+ /**
+ * Create a pattern which checks if the string form of a given object starts
+ * with a specific string.
+ *
+ * @param <RetType> The type returned by the matcher.
+ * @param <InpType> The type being matched against.
+ *
+ * @param pattern The string to check against.
+ * @param action The action to execute.
+ *
+ * @return A pattern which functions as described.
+ */
+ static <RetType, InpType> ComplexPattern<RetType, String, InpType> startsWith(
+ String pattern,
+ Function<String, RetType> action)
+ {
+ return from((input) -> {
+ String objString = input.toString();
+
+ if (objString.startsWith(pattern)) {
+ return Pair.pair(
+ true,
+ objString.substring(
+ pattern.length()));
+ } else {
+ return Pair.pair(false, null);
+ }
+ }, (ignored, input) -> action.apply(input));
+ }
} \ No newline at end of file
diff --git a/base/src/main/java/bjc/utils/patterns/FunctionalPattern.java b/base/src/main/java/bjc/utils/patterns/FunctionalPattern.java
index e4b4a3d..1e9dbab 100644
--- a/base/src/main/java/bjc/utils/patterns/FunctionalPattern.java
+++ b/base/src/main/java/bjc/utils/patterns/FunctionalPattern.java
@@ -7,11 +7,11 @@ import bjc.data.*;
class FunctionalPattern<ReturnType, PredType, InputType>
implements ComplexPattern<ReturnType, PredType, InputType> {
- private final Function<InputType, IPair<Boolean, PredType>> matcher;
+ private final Function<InputType, Pair<Boolean, PredType>> matcher;
private final BiFunction<InputType, PredType, ReturnType> accepter;
FunctionalPattern(
- Function<InputType, IPair<Boolean, PredType>> matcher,
+ Function<InputType, Pair<Boolean, PredType>> matcher,
BiFunction<InputType, PredType, ReturnType> accepter) {
super();
this.matcher = matcher;
@@ -19,7 +19,7 @@ class FunctionalPattern<ReturnType, PredType, InputType>
}
@Override
- public IPair<Boolean, PredType> matches(InputType input) {
+ public Pair<Boolean, PredType> matches(InputType input) {
return matcher.apply(input);
}
diff --git a/base/src/main/java/bjc/utils/patterns/FunctionalPatternMatcher.java b/base/src/main/java/bjc/utils/patterns/FunctionalPatternMatcher.java
index 5a214d3..e370fa0 100644
--- a/base/src/main/java/bjc/utils/patterns/FunctionalPatternMatcher.java
+++ b/base/src/main/java/bjc/utils/patterns/FunctionalPatternMatcher.java
@@ -11,7 +11,7 @@ import bjc.functypes.*;
* @param <InputType> The type to match against.
*/
public class FunctionalPatternMatcher<ReturnType, InputType>
- implements IPatternMatcher<ReturnType, InputType> {
+ implements PatternMatcher<ReturnType, InputType> {
private final ThrowFunction<InputType, ReturnType, NonExhaustiveMatch> matcher;
diff --git a/base/src/main/java/bjc/utils/patterns/IPatternMatcher.java b/base/src/main/java/bjc/utils/patterns/IPatternMatcher.java
deleted file mode 100644
index b688a47..0000000
--- a/base/src/main/java/bjc/utils/patterns/IPatternMatcher.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package bjc.utils.patterns;
-
-import java.util.function.*;
-
-import bjc.functypes.*;
-
-/**
- * Represents a pattern matcher against a series of patterns.
- *
- * @author Ben Culkin
- *
- * @param <ReturnType> The type returned from matching the patterns.
- * @param <InputType> The type to match against.
- */
-@FunctionalInterface
-public interface IPatternMatcher<ReturnType, InputType> {
- /**
- * Match an input object against a set of patterns.
- *
- * @param input The object to match against.
- *
- * @return The result of matching against the object.
- *
- * @throws NonExhaustiveMatch If none of the patterns in this set match
- */
- ReturnType matchFor(InputType input) throws NonExhaustiveMatch;
-
- /**
- * Create a pattern matcher against a static set of patterns.
- *
- * @param <RetType> The type returned from matching the patterns.
- * @param <InpType> The type to match against.
- *
- * @param patterns The set of patterns to match on.
- *
- * @return A pattern matcher which matches on the given patterns.
- */
- @SafeVarargs
- static <RetType, InpType> IPatternMatcher<RetType, InpType> matchingOn(
- ComplexPattern<RetType, ?, InpType>... patterns) {
- return new PatternMatcher<>(patterns);
- }
-
- /**
- * Create a pattern matcher from a handler function.
- *
- * @param <RetType> The type returned by the matcher.
- * @param <InpType> The type to match against.
- *
- * @param handler The handler function.
- *
- * @return A pattern matcher defined by the given handler.
- */
- static <RetType, InpType> IPatternMatcher<RetType, InpType> from(
- ThrowFunction<InpType, RetType, NonExhaustiveMatch> handler) {
- return new FunctionalPatternMatcher<>(handler);
- }
-
- /**
- * Create a pattern matcher which applies a transform to its input.
- *
- * @param <NewInput> The new input type to use.
- * @param transformer The function to convert from the new input to the old input.
- *
- * @return A pattern matcher which takes values of the new type instead.
- */
- default <NewInput> IPatternMatcher<ReturnType, NewInput> transformInput(
- Function<NewInput, InputType> transformer) {
- return from(inp -> matchFor(transformer.apply(inp)));
- }
-
- /**
- * Create a pattern matcher which applies a transform to its output.
- *
- * @param <NewOutput> The new output type to use.
- *
- * @param transformer The function to convert from the new output to the old output.
- *
- * @return A pattern matcher which takes values of the new type instead.
- */
- default <NewOutput> IPatternMatcher<NewOutput, InputType> transformOutput(
- Function<ReturnType, NewOutput> transformer) {
- return from(inp -> transformer.apply(matchFor(inp)));
- }
-} \ No newline at end of file
diff --git a/base/src/main/java/bjc/utils/patterns/MutablePatternMatcher.java b/base/src/main/java/bjc/utils/patterns/MutablePatternMatcher.java
index 7900262..28e9cd7 100644
--- a/base/src/main/java/bjc/utils/patterns/MutablePatternMatcher.java
+++ b/base/src/main/java/bjc/utils/patterns/MutablePatternMatcher.java
@@ -13,9 +13,10 @@ import bjc.data.*;
* @author Ben Culkin
*
* @param <ReturnType> The type returned by the pattern matcher.
+ * @param <InputType> The type of the input to match against.
*/
public class MutablePatternMatcher<ReturnType, InputType>
- implements IPatternMatcher<ReturnType, InputType>{
+ implements PatternMatcher<ReturnType, InputType> {
private final List<ComplexPattern<ReturnType, Object, InputType>> patterns;
/**
@@ -45,15 +46,15 @@ public class MutablePatternMatcher<ReturnType, InputType>
@Override
public ReturnType matchFor(InputType input) throws NonExhaustiveMatch {
Iterator<ComplexPattern<ReturnType, Object, InputType>> iterator;
- for (iterator = new NonCMEIterator<>(patterns);
- iterator.hasNext();) {
+ iterator = new NonCMEIterator<>(patterns);
+ while(iterator.hasNext()) {
ComplexPattern<ReturnType, Object, InputType> pattern = iterator.next();
- IPair<Boolean, Object> matches = pattern.matches(input);
+ Pair<Boolean, Object> matches = pattern.matches(input);
- if (matches.getLeft()) {
- pattern.apply(input, matches.getRight());
- }
+ matches.doWith((bool, obj) -> {
+ if (bool) pattern.apply(input, obj);
+ });
}
throw new NonExhaustiveMatch("Non-exhaustive match against " + input);
diff --git a/base/src/main/java/bjc/utils/patterns/Pattern.java b/base/src/main/java/bjc/utils/patterns/Pattern.java
index e03623e..c9902e8 100644
--- a/base/src/main/java/bjc/utils/patterns/Pattern.java
+++ b/base/src/main/java/bjc/utils/patterns/Pattern.java
@@ -1,11 +1,5 @@
package bjc.utils.patterns;
-import java.util.*;
-import java.util.function.*;
-import java.util.regex.*;
-
-import bjc.data.*;
-
/**
* A simpler version of ComplexPattern, which always applies against Object
*
diff --git a/base/src/main/java/bjc/utils/patterns/PatternMatcher.java b/base/src/main/java/bjc/utils/patterns/PatternMatcher.java
index e2ae9f6..40bf42b 100644
--- a/base/src/main/java/bjc/utils/patterns/PatternMatcher.java
+++ b/base/src/main/java/bjc/utils/patterns/PatternMatcher.java
@@ -1,41 +1,85 @@
package bjc.utils.patterns;
-import bjc.data.*;
+import java.util.function.*;
+
+import bjc.functypes.*;
/**
- * Implements pattern-matching (of a sort) against a collection of patterns.
+ * Represents a pattern matcher against a series of patterns.
*
* @author Ben Culkin
- *
- * @param <ReturnType> The type returned by the pattern.
+ *
+ * @param <ReturnType> The type returned from matching the patterns.
+ * @param <InputType> The type to match against.
*/
-public class PatternMatcher<ReturnType, InputType>
- implements IPatternMatcher<ReturnType, InputType> {
- private final ComplexPattern<ReturnType, Object, InputType>[] patterns;
+@FunctionalInterface
+public interface PatternMatcher<ReturnType, InputType> {
+ /**
+ * Match an input object against a set of patterns.
+ *
+ * @param input The object to match against.
+ *
+ * @return The result of matching against the object.
+ *
+ * @throws NonExhaustiveMatch If none of the patterns in this set match
+ */
+ ReturnType matchFor(InputType input) throws NonExhaustiveMatch;
/**
- * Create a new pattern matcher.
+ * Create a pattern matcher against a static set of patterns.
*
- * @param patterns The set of patterns to match against.
+ * @param <RetType> The type returned from matching the patterns.
+ * @param <InpType> The type to match against.
+ *
+ * @param patterns The set of patterns to match on.
+ *
+ * @return A pattern matcher which matches on the given patterns.
*/
- @SuppressWarnings("unchecked")
@SafeVarargs
- public PatternMatcher(ComplexPattern<ReturnType, ?, InputType>...patterns) {
- // Note: this may seem a somewhat questionable cast, but because we never
- // actually do anything with the value who has a type matching the second
- // parameter, this should be safe
- this.patterns = (ComplexPattern<ReturnType, Object, InputType>[]) patterns;
+ static <RetType, InpType> PatternMatcher<RetType, InpType> matchingOn(
+ ComplexPattern<RetType, ?, InpType>... patterns) {
+ return new SimplePatternMatcher<>(patterns);
+ }
+
+ /**
+ * Create a pattern matcher from a handler function.
+ *
+ * @param <RetType> The type returned by the matcher.
+ * @param <InpType> The type to match against.
+ *
+ * @param handler The handler function.
+ *
+ * @return A pattern matcher defined by the given handler.
+ */
+ static <RetType, InpType> PatternMatcher<RetType, InpType> from(
+ ThrowFunction<InpType, RetType, NonExhaustiveMatch> handler) {
+ return new FunctionalPatternMatcher<>(handler);
+ }
+
+ /**
+ * Create a pattern matcher which applies a transform to its input.
+ *
+ * @param <NewInput> The new input type to use.
+ * @param transformer The function to convert from the new input to the old input.
+ *
+ * @return A pattern matcher which takes values of the new type instead.
+ */
+ default <NewInput> PatternMatcher<ReturnType, NewInput> transformInput(
+ Function<NewInput, InputType> transformer) {
+ return from(inp -> matchFor(transformer.apply(inp)));
}
- @Override
- public ReturnType matchFor(InputType input) throws NonExhaustiveMatch {
- for (ComplexPattern<ReturnType, Object, InputType> pattern : patterns) {
- IPair<Boolean, Object> matches = pattern.matches(input);
- if (matches.getLeft()) {
- pattern.apply(input, matches.getRight());
- }
- }
-
- throw new NonExhaustiveMatch("Non-exhaustive match against " + input);
+ /**
+ * Create a pattern matcher which applies a transform to its output.
+ *
+ * @param <NewOutput> The new output type to use.
+ *
+ * @param transformer The function to convert from the new output to the old output.
+ *
+ * @return A pattern matcher which takes values of the new type instead.
+ */
+ default <NewOutput> PatternMatcher<NewOutput, InputType> transformOutput(
+ Function<ReturnType, NewOutput> transformer) {
+ return from(inp -> transformer.apply(matchFor(inp)));
}
-}
+} \ No newline at end of file
diff --git a/base/src/main/java/bjc/utils/patterns/SimplePatternMatcher.java b/base/src/main/java/bjc/utils/patterns/SimplePatternMatcher.java
new file mode 100644
index 0000000..fea947a
--- /dev/null
+++ b/base/src/main/java/bjc/utils/patterns/SimplePatternMatcher.java
@@ -0,0 +1,41 @@
+package bjc.utils.patterns;
+
+import bjc.data.*;
+
+/**
+ * Implements pattern-matching (of a sort) against a collection of patterns.
+ *
+ * @author Ben Culkin
+ *
+ * @param <ReturnType> The type returned by the pattern.
+ */
+public class SimplePatternMatcher<ReturnType, InputType>
+ implements PatternMatcher<ReturnType, InputType> {
+ private final ComplexPattern<ReturnType, Object, InputType>[] patterns;
+
+ /**
+ * Create a new pattern matcher.
+ *
+ * @param patterns The set of patterns to match against.
+ */
+ @SuppressWarnings("unchecked")
+ @SafeVarargs
+ public SimplePatternMatcher(ComplexPattern<ReturnType, ?, InputType>...patterns) {
+ // Note: this may seem a somewhat questionable cast, but because we never
+ // actually do anything with the value who has a type matching the second
+ // parameter, this should be safe
+ this.patterns = (ComplexPattern<ReturnType, Object, InputType>[]) patterns;
+ }
+
+ @Override
+ public ReturnType matchFor(InputType input) throws NonExhaustiveMatch {
+ for (ComplexPattern<ReturnType, Object, InputType> pattern : patterns) {
+ Pair<Boolean, Object> matches = pattern.matches(input);
+ if (matches.getLeft()) {
+ pattern.apply(input, matches.getRight());
+ }
+ }
+
+ throw new NonExhaustiveMatch("Non-exhaustive match against " + input);
+ }
+}
diff --git a/base/src/main/java/bjc/utils/patterns/SimplePatttern.java b/base/src/main/java/bjc/utils/patterns/SimplePatttern.java
index 1601894..db53287 100644
--- a/base/src/main/java/bjc/utils/patterns/SimplePatttern.java
+++ b/base/src/main/java/bjc/utils/patterns/SimplePatttern.java
@@ -34,7 +34,7 @@ public interface SimplePatttern<ReturnType> extends Pattern<ReturnType, Void> {
}
@Override
- default IPair<Boolean, Void> matches(Object input) {
- return new Pair<>(doesMatch(input), null);
+ default Pair<Boolean, Void> matches(Object input) {
+ return new SimplePair<>(doesMatch(input), null);
}
} \ No newline at end of file