For instance, a pattern written in the notation for complex numbers can be parsed as follows:
Matcher m = Matchbox.matcher("(1.0+%yi)", Complex.class); Subst sub = new NonLinearSubst(); if(m.match(new Complex(1, 5), sub)) System.out.println(sub);
In order for this to work with a custom notation for a type T, one must implement a method T.matcher(String pat, ParsePosition pos), which parses a sub-pattern starting at a given position and returns a matcher object corresponding to the parsed pattern, and also updates the position to indicate the sub-pattern that was consumed. The matcher method for the Complex type can be written as follows:
public static Matcher matcher(String pat, ParsePosition pos) throws ParseFail { Matcher mr, mi = null; if(!Matchbox.matchChar('(', pat, pos)) throw new ParseFail(); mr = Matchbox.numberMatcher(pat, pos); if(pat.charAt(pos.getIndex()) == '+') { Matchbox.matchChar('+', pat, pos); mi = Matchbox.numberMatcher(pat, pos); if(!Matchbox.matchChar('i', pat, pos)) throw new ParseFail(); } if(!Matchbox.matchChar(')', pat, pos)) throw new ParseFail(); return new ComplexMatcher(mr, mi); }The numberMatcher(pat, pos) function above is predefined in myPatterns. It parses at the given offset either a variable occurrence or a sub-pattern for a number. In case of a parse error, the method must throw a ParseFail exception.
In case of success, the method must return a matcher. For Complex numbers, one has to define an instantiate the following class:
class ComplexMatcher implements Matcher { Matcher mr, mi; public ComplexMatcher(Matcher re, Matcher im) { mr = re; mi = im; } public boolean match(Object data, Subst sub) { if(!(data instanceof Complex)) return false; Complex c = (Complex)data; return mr.match(c.re, sub) && (mi == null || mi.match(c.im, sub)); } }That is, the ComplexMatcher represents a compiled pattern written in the complex notation, which contains a sub-matcher for the real part, and an optional sub-matcher for the imaginary part. Thus, the match() method invokes these sub-matchers on the given data (after checking that the data is a Complex), and succeeds if all the sub-matchers succeed.
That's all about defining custom notations. More elaborate examples are included in the myPatterns distribution, including a custom notation for red-black trees.