LeaVerou/prism — pull request #334 by zeitgeist87 (2014-08-14 19:00:18+00:00)
Title: Add small on the fly parser compiler

Hi,

First of all I know, that `notInBetween` is a horrible name for a new property, but I am just awful at naming things. I know, that this compiler would blow up the size of Prism considerably, so feel free to reject the PR. I just implemented it for the fun of it ;).

I have also created a benchmark: http://jsperf.com/test-compiled-parsers-for-prism

This patch adds the new property `notInBetween`, which can contain an
array of characters. During execution the array is compiled into a small
efficient parser, which can check if the matched pattern is not
in between the specified characters.

By default the start and end characters are the same, the escape
character is `\` and multiline is assumed to be `true`. But it is
possible to modify the default values by using an object literal instead
of a string. The following example should illustrate how it works:

```js
'comment': {
pattern: /\/\*[\w\W]*?\*\/|\/\/.*/g,
notInBetween: [ '"', '\'', { start: '/', multiline: false, escape: '\\' }]
},
```

The generated parser for the above code snipped looks like this:

```js
function(match, lastIndex) {
var in34 = !!this.in34;
var in39 = !!this.in39;
var in47 = !!this.in47;
var esc92 = !!this.esc92;
var i = lastIndex || 0,
str = match.input,
len = match.index;
for (; i < len; ++i) {
switch (str.charCodeAt(i)) {
case 34:
in34 = (!in34 || esc92) && !in39 && !in47;
esc92 = false;
break;
case 39:
in39 = !in34 && (!in39 || esc92) && !in47;
esc92 = false;
break;
case 47:
in47 = !in34 && !in39 && (!in47 || esc92);
esc92 = false;
break;
case 10:
in47 = false;
esc92 = false;
break;
case 92:
esc92 = !esc92;
break;
default:
esc92 = false;
break;
}
};
this.in34 = in34;
this.in39 = in39;
this.in47 = in47;
this.esc92 = esc92;
return !in34 && !in39 && !in47;
}
```