// worst-case scenario for the grammar below nines = "9999999999" for (var i = 0; i < 12; i += 1) nines += nines ometa M { digit = '0' -> 'a' | '1' -> 'b' | '2' -> 'c' | '3' -> 'd' | '4' -> 'e' | '5' -> 'f' | '6' -> 'g' | '7' -> 'h' | '8' -> 'i' | '9' -> 'j', digits = digit* } start = (new Date()).getTime() M.matchAll(nines, "digits") t1 = (new Date()).getTime() - start // firefox 3.5.7 on alex's mbp: 16803 15776 15301 // safari 4.0.4 on alex's mpb: 3761 3777 3760 // chrome 4.0.249.49 on alex's mbp: 2998 2925 3012 // here we create a subgrammar of M that overrides the digit rule w/ a version that uses a jumptable N = M.delegated() N.digit = function() { var $elf = this var x = $elf._apply('anything') var f = ({ '0': function() { return 'a' }, '1': function() { return 'b' }, '2': function() { return 'c' }, '3': function() { return 'd' }, '4': function() { return 'e' }, '5': function() { return 'f' }, '6': function() { return 'g' }, '7': function() { return 'h' }, '8': function() { return 'i' }, '9': function() { return 'j' } })[x] if (!f) throw fail return f() } start = (new Date()).getTime() N.matchAll(nines, "digits") t2 = (new Date()).getTime() - start // firefox 3.5.7 on alex's mbp: 1479 2557 1399 // safari 4.0.4 on alex's mpb: 342 385 479 // chrome 4.0.249.49 on alex's mbp: 516 429 450 // here we create a subgrammar of M that overrides the digit rule w/ a version that uses a jumptable O = M.delegated() O.digit = function() { var $elf = this return (function() { switch ($elf._apply('anything')) { case '0': return 'a'; case '1': return 'b'; case '2': return 'c'; case '3': return 'd'; case '4': return 'e'; case '5': return 'f'; case '6': return 'g'; case '7': return 'h'; case '8': return 'i'; case '9': return 'j'; default: throw fail } })() } start = (new Date()).getTime() O.matchAll(nines, "digits") t3 = (new Date()).getTime() - start // firefox 3.5.7 on alex's mbp: 867 875 869 // safari 4.0.4 on alex's mpb: 245 274 224 // chrome 4.0.249.49 on alex's mbp: 330 212 344