For instance, a pattern written in the notation for complex numbers can be parsed as follows:
var m = matcher(Complex, "(%x+%yi)"); // m is the parsed pattern (a function) var s = m(new Complex(1, -1)); // matches the complex with the compiled pattern
In order for this to work with a custom notation for a type T, one must implement a method T.prototype.matcher(pattern, offset), which parses a sub-pattern starting at a given offset, and returns (1) an updated offset, indicating the sub-pattern that was consumed, and (2) a matcher function corresponding to the parsed pattern. The matcher method for the Complex type can be written as follows:
Complex.prototype.matcher = function(pat, off) {
var m1, m2, res;
off = matchChar("(", pat, off);
res = parseType(Number, pat, off);
off = res[0]; m1 = res[1];
if(pat.charAt(off) == "+") {
off = matchChar("+", pat, off);
res = parseType(Number, pat, off);
off = res[0]; m2 = res[1];
off = matchChar("i", pat, off);
}
off = matchChar(")", pat, off);
return [off, function(data, sub) {
if(data == null) throw "fail";
m1(data.re, sub);
if(m2 !== undefined) m2(data.im, sub);
}];
}
The parseType(type, pat, off) function above is predefined in
myPatterns. It parses at the given offset either a variable occurrence
or a sub-pattern written in the notation for the given type. In the case
of complex numbers, the sub-patterns are all of type Number, so this
function will use the predefined matcher() method for type Number to
parse them. If some sub-pattern were written in a custom notation,
the corresponding matcher method would have to be implemented.
Like in interpreted patterns, the outermost parentheses in a pattern can be omitted by using function pmatcher() instead of matcher(). Thus, pmatcher(Complex, "%x+%yi") gives the same result as matcher(Complex, "(%x+%yi)").