From 4c0f972c4616eb549a098c3ef40d527eb542d7a6 Mon Sep 17 00:00:00 2001 From: Ben Culkin Date: Sat, 21 Nov 2020 16:51:04 -0500 Subject: Add basic pattern matching Adds a basic pattern matching implementation. Not perfect, but pretty good, considering what we have to work with --- .../bjc/utils/patterns/MutablePatternMatcher.java | 84 ++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 base/src/main/java/bjc/utils/patterns/MutablePatternMatcher.java (limited to 'base/src/main/java/bjc/utils/patterns/MutablePatternMatcher.java') 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..7900262 --- /dev/null +++ b/base/src/main/java/bjc/utils/patterns/MutablePatternMatcher.java @@ -0,0 +1,84 @@ +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 The type returned by the pattern matcher. + */ +public class MutablePatternMatcher + implements IPatternMatcher{ + private final List> 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... patterns) { + this(); + + for (ComplexPattern 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) pattern); + } + } + + @Override + public ReturnType matchFor(InputType input) throws NonExhaustiveMatch { + Iterator> iterator; + for (iterator = new NonCMEIterator<>(patterns); + iterator.hasNext();) { + ComplexPattern pattern = iterator.next(); + + IPair matches = pattern.matches(input); + + if (matches.getLeft()) { + pattern.apply(input, matches.getRight()); + } + } + + 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 pattern) { + return patterns.add((ComplexPattern) pattern); + } + + /** + * Remove a pattern from this pattern matcher. + * + * @param pattern The pattern to remove. + * + * @return Whether or not the pattern was removed. + */ + public boolean removePattern(ComplexPattern pattern) { + return patterns.remove(pattern); + } +} -- cgit v1.2.3