For example, let us define the usual mathematical notation for the following simple type of complex numbers.
function Complex(re, im) { this.re = re; this.im = im; }The usual notation for complex numbers is "a + bi" for a complex number with an imaginary part, and simply "a" for complex numbers whith a no imaginary part. However, in myPatterns, all notations must start with an open parenthesis (one of "([{") and end with the corresponding closing parenthesis (")]}"). (This restriction ensures that arbitrary notations designed by different people can always be composed unambiguosly.) Thus, the implemented notation will be in fact "(a + bi)" and "(a)", respectively.
Defining this notation for Complex objects is simply done by redefining the Complex.matches() method, with some code implementing the new notation.
Complex.prototype.matches = function(pat, off, sub) { off = matchChar("(", pat, off); off = matchData(this.re, pat, off, sub); if(pat.charAt(off) == "+") { off = matchChar("+", pat, off); off = matchData(this.im, pat, off, sub); off = matchChar("i", pat, off); } else if(this.im == 0) ; // already done else throw "fail"; off = matchChar(")", pat, off); return off; }This method matches in fact a sub-pattern at a given offset with the current Complex. The third argument is the substitution already accumulated while matching the portion of the pattern that appears before the current sub-pattern (i.e. between the beginning of the pattern and the given offset). This substitution must simply be passed to all the worker functions that require it. There are predefined worker function for matching a character (matchChar()), a token (matchToken()), and a sub-data (matchData()). If the match is successful, the method must return an updated offset, reflecting the sub-pattern that has been consumed. If the match is unsuccessful, the method must throw a "fail" exception.
Using this notation, match(new Complex(1, 2), "(%x+%yi)") returns {x:1, y:2}; match(new Complex(3, 0), "(%x+%yi)") returns {x:3, y:0}, and match(new Complex(3, 0), "(%x)") returns {x:3}.
For more convenience, the predefined function pmatch() automatically adds the outermost pair of parentheses around a pattern before calling match(). Thus, one may write pmatch(new Complex(3, 0), "%x+%yi") instead of match(new Complex(3, 0), "(%x+%yi)"). However, when the complex notation is used as a sub-pattern, parentheses remain mandatory: match(new Complex(3, 0), "[(%x+%yi),(%a+%bi)]")
That's all about defining custom notations. More examples are available in the distribution.