diff options
Diffstat (limited to 'base/src/main/java/bjc/utils/patterns/MutablePatternMatcher.java')
| -rw-r--r-- | base/src/main/java/bjc/utils/patterns/MutablePatternMatcher.java | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/base/src/main/java/bjc/utils/patterns/MutablePatternMatcher.java b/base/src/main/java/bjc/utils/patterns/MutablePatternMatcher.java new file mode 100644 index 0000000..176f588 --- /dev/null +++ b/base/src/main/java/bjc/utils/patterns/MutablePatternMatcher.java @@ -0,0 +1,86 @@ +package bjc.utils.patterns; + +import java.util.*; + +import bjc.data.*; + +/** + * A pattern matcher over a mutable set of patterns. + * + * Note that modifying a pattern matcher while it is currently doing pattern + * matching is a wonderful way to cause strange behavior. + * + * @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 PatternMatcher<ReturnType, InputType> { + private final List<ComplexPattern<ReturnType, Object, InputType>> patterns; + + /** + * Create a new mutable pattern matcher with no patterns. + */ + public MutablePatternMatcher() { + patterns = new ArrayList<>(); + } + + /** + * Create a new mutable pattern matcher with the given set of patterns. + * + * @param patterns The set of patterns to match on. + */ + @SuppressWarnings("unchecked") + public MutablePatternMatcher(ComplexPattern<ReturnType, ?, InputType>... patterns) { + this(); + + for (ComplexPattern<ReturnType, ?, InputType> pattern : 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.add((ComplexPattern<ReturnType, Object, InputType>) pattern); + } + } + + @Override + public ReturnType matchFor(InputType input) throws NonExhaustiveMatch { + Iterator<ComplexPattern<ReturnType, Object, InputType>> iterator; + iterator = new NonCMEIterator<>(patterns); + while(iterator.hasNext()) { + ComplexPattern<ReturnType, Object, InputType> pattern = iterator.next(); + + Pair<Boolean, Object> matches = pattern.matches(input); + + matches.doWith((bool, obj) -> { + if (bool) pattern.apply(input, obj); + }); + } + + throw new NonExhaustiveMatch("Non-exhaustive match against " + input); + } + + /** + * Add a pattern to this pattern matcher. + * + * @param pattern The pattern to add. + * + * @return Whether or not the pattern was added. + */ + @SuppressWarnings("unchecked") + public boolean addPattern(ComplexPattern<ReturnType, ?, InputType> pattern) { + return patterns.add((ComplexPattern<ReturnType, Object, InputType>) pattern); + } + + /** + * Remove a pattern from this pattern matcher. + * + * @param pattern The pattern to remove. + * + * @return Whether or not the pattern was removed. + */ + @SuppressWarnings("unlikely-arg-type") + public boolean removePattern(ComplexPattern<ReturnType, ?, InputType> pattern) { + return patterns.remove(pattern); + } +} |
