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. * @param The type of the input to match against. */ 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; iterator = new NonCMEIterator<>(patterns); while(iterator.hasNext()) { ComplexPattern pattern = iterator.next(); IPair 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 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); } }