parsed notations

In all the previous examples, the custom patterns were interpreted at each call of function match(). Especially when match() occurs in a loop, this is not optimal in terms of performance. Fortunately, patterns can be parsed before being used in a match by using the predefined function matcher(type, pattern), that takes a pattern written in some custom notation and the type associated to this notation, and returns a matcher, that is, a function (or more exactly, a "closure") matching some data with the (parsed form of the) pattern.

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)").


Next: Performance