r90473 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r90472‎ | r90473 | r90474 >
Date:18:28, 20 June 2011
Author:brion
Status:deferred
Tags:
Comment:
First-pass extension adaptation of ParserPlayground gadget bits. Will be reworked significantly in next few days to integrate better into WikiEditor & prep for merging other bits.
Gadget will be updated to use these copies.
Modified paths:
  • /trunk/extensions/ParserPlayground (added) (history)
  • /trunk/extensions/ParserPlayground/ParserPlayground.hooks.php (added) (history)
  • /trunk/extensions/ParserPlayground/ParserPlayground.i18n.php (added) (history)
  • /trunk/extensions/ParserPlayground/ParserPlayground.php (added) (history)
  • /trunk/extensions/ParserPlayground/README (added) (history)
  • /trunk/extensions/ParserPlayground/modules (added) (history)
  • /trunk/extensions/ParserPlayground/modules/ext.parserPlayground.classicParser.js (added) (history)
  • /trunk/extensions/ParserPlayground/modules/ext.parserPlayground.css (added) (history)
  • /trunk/extensions/ParserPlayground/modules/ext.parserPlayground.fakeParser.js (added) (history)
  • /trunk/extensions/ParserPlayground/modules/ext.parserPlayground.hashMap.js (added) (history)
  • /trunk/extensions/ParserPlayground/modules/ext.parserPlayground.js (added) (history)
  • /trunk/extensions/ParserPlayground/modules/ext.parserPlayground.pegParser.js (added) (history)
  • /trunk/extensions/ParserPlayground/modules/lib.jsdiff.js (added) (history)
  • /trunk/extensions/ParserPlayground/modules/lib.pegjs.js (added) (history)
  • /trunk/extensions/ParserPlayground/modules/pegParser.pegjs.txt (added) (history)

Diff [purge]

Index: trunk/extensions/ParserPlayground/ParserPlayground.i18n.php
@@ -0,0 +1,16 @@
 2+<?php
 3+/**
 4+ * Internationalisation for ParserPlayground extension
 5+ *
 6+ * @file
 7+ * @ingroup Extensions
 8+ */
 9+
 10+$messages = array();
 11+
 12+/** English
 13+ * @author Brion Vibber
 14+ */
 15+$messages['en'] = array(
 16+ 'parserplayground-desc' => 'Parser and editor experiments',
 17+);
Property changes on: trunk/extensions/ParserPlayground/ParserPlayground.i18n.php
___________________________________________________________________
Added: svn:eol-style
118 + native
Index: trunk/extensions/ParserPlayground/ParserPlayground.php
@@ -0,0 +1,79 @@
 2+<?php
 3+
 4+/**
 5+ * JS plugins for demoing & testing early stages of the new parser
 6+ * & visual editor projects: http://www.mediawiki.org/wiki/Future
 7+ *
 8+ * Extends and requires WikiEditor extension.
 9+ *
 10+ * Extension code is GPLv2 following MediaWiki base.
 11+ * Ace editor JS code follows its own license, see in the 'ace' subdir.
 12+ */
 13+
 14+$wgExtensionCredits['other'][] = array(
 15+ 'path' => __FILE__,
 16+ 'name' => 'ParserPlayground',
 17+ 'url' => 'http://www.mediawiki.org/wiki/Extension:ParserPlayground',
 18+ 'author' => array( 'Brion Vibber', ),
 19+ 'descriptionmsg' => 'parserplayground-desc',
 20+);
 21+
 22+$dir = dirname( __FILE__ );
 23+$wgAutoloadClasses['ParserPlaygroundHooks'] = $dir . '/ParserPlayground.hooks.php';
 24+$wgExtensionMessagesFiles['CodeEditor'] = $dir . '/ParserPlayground.i18n.php';
 25+
 26+$wgHooks['EditPage::showEditForm:initial'][] = 'ParserPlaygroundHooks::editPageShowEditFormInitial';
 27+
 28+$tpl = array(
 29+ 'localBasePath' => dirname( __FILE__ ) . '/modules',
 30+ 'remoteExtPath' => 'ParserPlayground/modules',
 31+ 'group' => 'ext.wikiEditor',
 32+);
 33+/*
 34+$wgResourceModules['ext.codeEditor'] = array(
 35+ 'scripts' => 'ext.codeEditor.js',
 36+ 'dependencies' => array(
 37+ 'ext.wikiEditor',
 38+ 'jquery.codeEditor'
 39+ ),
 40+) + $tpl;
 41+
 42+$wgResourceModules['jquery.codeEditor'] = array(
 43+ 'scripts' => 'jquery.codeEditor.js',
 44+ 'dependencies' => array(
 45+ 'jquery.wikiEditor',
 46+ 'ext.codeEditor.ace',
 47+ ),
 48+ 'messages' => array(
 49+ 'codeeditor-toolbar-toggle'
 50+ )
 51+) + $tpl;
 52+
 53+// Minimal bundling of a couple bits of Ace
 54+$wgResourceModules['ext.codeEditor.ace'] = array(
 55+ 'scripts' => array(
 56+ 'ace/ace-uncompressed.js',
 57+ 'ace/mode-javascript.js',
 58+ 'ace/mode-css.js',
 59+ ),
 60+) + $tpl;
 61+*/
 62+
 63+$wgResourceModules['ext.parserPlayground'] = array(
 64+ 'scripts' => array(
 65+ 'lib.jsdiff.js',
 66+ 'lib.pegjs.js',
 67+ 'ext.parserPlayground.hashMap.js',
 68+ 'ext.parserPlayground.fakeParser.js',
 69+ 'ext.parserPlayground.classicParser.js',
 70+ 'ext.parserPlayground.pegParser.js',
 71+ 'ext.parserPlayground.js',
 72+ ),
 73+ 'styles' => array(
 74+ 'ext.parserPlayground.css',
 75+ ),
 76+ 'dependencies' => array(
 77+ 'ext.wikiEditor'
 78+ ),
 79+) + $tpl;
 80+
Property changes on: trunk/extensions/ParserPlayground/ParserPlayground.php
___________________________________________________________________
Added: svn:eol-style
181 + native
Index: trunk/extensions/ParserPlayground/modules/ext.parserPlayground.pegParser.js
@@ -0,0 +1,64 @@
 2+/**
 3+ * Wrap a parser generated with pegjs into the FakeParser class,
 4+ * so will use FakeParser's HTML output and round-tripping functions.
 5+ *
 6+ * If installed as a user script or to customize, set parserPlaygroundPegPage
 7+ * to point at the MW page name containing the parser peg definition; default
 8+ * is 'MediaWiki:Gadget-ParserPlayground-PegParser.pegjs'.
 9+ */
 10+function PegParser(options) {
 11+ FakeParser.call(this, options);
 12+}
 13+
 14+$.extend(PegParser.prototype, FakeParser.prototype);
 15+
 16+PegParser.prototype.parseToTree = function(text, callback) {
 17+ this.initField(function() {
 18+ var $src = $('#pegparser-source');
 19+ if ($src.length) {
 20+ var parserSource = $src.val();
 21+ } else {
 22+ var parserSource = '';
 23+ }
 24+ var out, err;
 25+ try {
 26+ var parser = PEG.buildParser(parserSource);
 27+ out = parser.parse(text);
 28+ } catch (e) {
 29+ err = e;
 30+ } finally {
 31+ callback(out, err);
 32+ }
 33+ });
 34+}
 35+
 36+PegParser.prototype.initField = function(callback) {
 37+ var src = $('#pegparser-source');
 38+ if (src.length) {
 39+ src.show();
 40+ callback();
 41+ } else {
 42+ var area = $('<textarea id="pegparser-source" rows=25></textarea>').insertBefore('#wpTextbox1');
 43+ if ( typeof parserPlaygroundPegPage !== 'undefined' ) {
 44+ $.get(wgScriptPath + '/api' + wgScriptExtension, {
 45+ format: 'json',
 46+ action: 'query',
 47+ prop: 'revisions',
 48+ rvprop: 'content',
 49+ titles: parserPlaygroundPegPage
 50+ }, function(data, xhr) {
 51+ $.each(data.query.pages, function(i, page) {
 52+ if (page.revisions && page.revisions.length) {
 53+ $('#pegparser-source').val(page.revisions[0]['*']);
 54+ }
 55+ });
 56+ callback();
 57+ }, 'json');
 58+ } else {
 59+ $.get(wgExtensionAssetsPath + '/ParserPlayground/modules/pegParser.pegjs.txt', function(data) {
 60+ $('#pegparser-source').val(data);
 61+ callback();
 62+ }, 'text' );
 63+ }
 64+ }
 65+};
Property changes on: trunk/extensions/ParserPlayground/modules/ext.parserPlayground.pegParser.js
___________________________________________________________________
Added: svn:eol-style
166 + native
Index: trunk/extensions/ParserPlayground/modules/lib.jsdiff.js
@@ -0,0 +1,160 @@
 2+/*
 3+ * Javascript Diff Algorithm
 4+ * By John Resig (http://ejohn.org/)
 5+ * Modified by Chu Alan "sprite"
 6+ *
 7+ * Released under the MIT license.
 8+ *
 9+ * More Info:
 10+ * http://ejohn.org/projects/javascript-diff-algorithm/
 11+ */
 12+
 13+function escape(s) {
 14+ var n = s;
 15+ n = n.replace(/&/g, "&amp;");
 16+ n = n.replace(/</g, "&lt;");
 17+ n = n.replace(/>/g, "&gt;");
 18+ n = n.replace(/"/g, "&quot;");
 19+
 20+ return n;
 21+}
 22+
 23+function diffString( o, n ) {
 24+ o = o.replace(/\s+$/, '');
 25+ n = n.replace(/\s+$/, '');
 26+
 27+ var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/) );
 28+ var str = "";
 29+
 30+ var oSpace = o.match(/\s+/g);
 31+ if (oSpace == null) {
 32+ oSpace = ["\n"];
 33+ } else {
 34+ oSpace.push("\n");
 35+ }
 36+ var nSpace = n.match(/\s+/g);
 37+ if (nSpace == null) {
 38+ nSpace = ["\n"];
 39+ } else {
 40+ nSpace.push("\n");
 41+ }
 42+
 43+ if (out.n.length == 0) {
 44+ for (var i = 0; i < out.o.length; i++) {
 45+ str += '<del>' + escape(out.o[i]) + oSpace[i] + "</del>";
 46+ }
 47+ } else {
 48+ if (out.n[0].text == null) {
 49+ for (n = 0; n < out.o.length && out.o[n].text == null; n++) {
 50+ str += '<del>' + escape(out.o[n]) + oSpace[n] + "</del>";
 51+ }
 52+ }
 53+
 54+ for ( var i = 0; i < out.n.length; i++ ) {
 55+ if (out.n[i].text == null) {
 56+ str += '<ins>' + escape(out.n[i]) + nSpace[i] + "</ins>";
 57+ } else {
 58+ var pre = "";
 59+
 60+ for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {
 61+ pre += '<del>' + escape(out.o[n]) + oSpace[n] + "</del>";
 62+ }
 63+ str += " " + escape(out.n[i].text) + nSpace[i] + pre;
 64+ }
 65+ }
 66+ }
 67+
 68+ return str;
 69+}
 70+
 71+function randomColor() {
 72+ return "rgb(" + (Math.random() * 100) + "%, " +
 73+ (Math.random() * 100) + "%, " +
 74+ (Math.random() * 100) + "%)";
 75+}
 76+function diffString2( o, n ) {
 77+ o = o.replace(/\s+$/, '');
 78+ n = n.replace(/\s+$/, '');
 79+
 80+ var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/) );
 81+
 82+ var oSpace = o.match(/\s+/g);
 83+ if (oSpace == null) {
 84+ oSpace = ["\n"];
 85+ } else {
 86+ oSpace.push("\n");
 87+ }
 88+ var nSpace = n.match(/\s+/g);
 89+ if (nSpace == null) {
 90+ nSpace = ["\n"];
 91+ } else {
 92+ nSpace.push("\n");
 93+ }
 94+
 95+ var os = "";
 96+ var colors = new Array();
 97+ for (var i = 0; i < out.o.length; i++) {
 98+ colors[i] = randomColor();
 99+
 100+ if (out.o[i].text != null) {
 101+ os += '<span style="background-color: ' +colors[i]+ '">' +
 102+ escape(out.o[i].text) + oSpace[i] + "</span>";
 103+ } else {
 104+ os += "<del>" + escape(out.o[i]) + oSpace[i] + "</del>";
 105+ }
 106+ }
 107+
 108+ var ns = "";
 109+ for (var i = 0; i < out.n.length; i++) {
 110+ if (out.n[i].text != null) {
 111+ ns += '<span style="background-color: ' +colors[out.n[i].row]+ '">' +
 112+ escape(out.n[i].text) + nSpace[i] + "</span>";
 113+ } else {
 114+ ns += "<ins>" + escape(out.n[i]) + nSpace[i] + "</ins>";
 115+ }
 116+ }
 117+
 118+ return { o : os , n : ns };
 119+}
 120+
 121+function diff( o, n ) {
 122+ var ns = new Object();
 123+ var os = new Object();
 124+
 125+ for ( var i = 0; i < n.length; i++ ) {
 126+ if ( ns[ n[i] ] == null )
 127+ ns[ n[i] ] = { rows: new Array(), o: null };
 128+ ns[ n[i] ].rows.push( i );
 129+ }
 130+
 131+ for ( var i = 0; i < o.length; i++ ) {
 132+ if ( os[ o[i] ] == null )
 133+ os[ o[i] ] = { rows: new Array(), n: null };
 134+ os[ o[i] ].rows.push( i );
 135+ }
 136+
 137+ for ( var i in ns ) {
 138+ if ( ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1 ) {
 139+ n[ ns[i].rows[0] ] = { text: n[ ns[i].rows[0] ], row: os[i].rows[0] };
 140+ o[ os[i].rows[0] ] = { text: o[ os[i].rows[0] ], row: ns[i].rows[0] };
 141+ }
 142+ }
 143+
 144+ for ( var i = 0; i < n.length - 1; i++ ) {
 145+ if ( n[i].text != null && n[i+1].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null &&
 146+ n[i+1] == o[ n[i].row + 1 ] ) {
 147+ n[i+1] = { text: n[i+1], row: n[i].row + 1 };
 148+ o[n[i].row+1] = { text: o[n[i].row+1], row: i + 1 };
 149+ }
 150+ }
 151+
 152+ for ( var i = n.length - 1; i > 0; i-- ) {
 153+ if ( n[i].text != null && n[i-1].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null &&
 154+ n[i-1] == o[ n[i].row - 1 ] ) {
 155+ n[i-1] = { text: n[i-1], row: n[i].row - 1 };
 156+ o[n[i].row-1] = { text: o[n[i].row-1], row: i - 1 };
 157+ }
 158+ }
 159+
 160+ return { o: o, n: n };
 161+}
Property changes on: trunk/extensions/ParserPlayground/modules/lib.jsdiff.js
___________________________________________________________________
Added: svn:eol-style
1162 + native
Index: trunk/extensions/ParserPlayground/modules/ext.parserPlayground.css
@@ -0,0 +1,22 @@
 2+#mw-parser-popup .parseNode {
 3+ border: solid 1px transparent;
 4+}
 5+#mw-parser-popup .parseNodeHighlight {
 6+ border: solid 1px blue;
 7+}
 8+
 9+#mw-parser-popup .template {
 10+ background: #f8f8ff;
 11+}
 12+
 13+#mw-parser-popup del,
 14+#mw-parser-popup ins {
 15+ font-weight: bold;
 16+ color: red;
 17+}
 18+#mw-parser-popup del {
 19+ background: #FFFFAA;
 20+}
 21+#mw-parser-popup ins {
 22+ background: #CCFFCC;
 23+}
Property changes on: trunk/extensions/ParserPlayground/modules/ext.parserPlayground.css
___________________________________________________________________
Added: svn:eol-style
124 + native
Index: trunk/extensions/ParserPlayground/modules/ext.parserPlayground.classicParser.js
@@ -0,0 +1,191 @@
 2+var apiCallers = {};
 3+var apiCache = {};
 4+
 5+function callApi(params, callback) {
 6+ var api = wgScriptPath + '/api' + wgScriptExtension;
 7+ var key = JSON.stringify(params);
 8+ if (key in apiCallers && apiCallers[key]) {
 9+ apiCallers[key].push(callback);
 10+ } else if (key in apiCache) {
 11+ callback(apiCache[key] && apiCache[key]);
 12+ } else {
 13+ apiCallers[key] = [callback];
 14+ $.ajax({
 15+ url: api,
 16+ data: params,
 17+ type: 'POST',
 18+ dataType: 'json',
 19+ success: function(data, xhr) {
 20+ var callbacks = apiCallers[key];
 21+ apiCallers[key] = null;
 22+ apiCache[key] = data;
 23+ $.each(callbacks, function(i, aCallback) {
 24+ aCallback(data);
 25+ });
 26+ }
 27+ });
 28+ }
 29+}
 30+
 31+/**
 32+ * Stub wrapper for using MediaWiki's parser via API
 33+ */
 34+function MediaWikiParser(context) {
 35+ this.context = context;
 36+}
 37+
 38+/**
 39+ * Run wiki text through the preprocessor to produce a preprocessor parse tree
 40+ * (XML tree, not JSON).
 41+ *
 42+ * @param {string} text
 43+ * @param {function(tree, error)} callback
 44+ */
 45+MediaWikiParser.prototype.parseToTree = function(text, callback) {
 46+ callApi({
 47+ action: 'expandtemplates', // not really what we want, but it'll do
 48+ title: wgPageName,
 49+ text: text,
 50+ generatexml: '1',
 51+ format: 'json'
 52+ }, function(data, xhr) {
 53+ if (typeof data.parsetree['*'] === 'string') {
 54+ var parser = new DOMParser();
 55+ var dom = parser.parseFromString(data.parsetree['*'], 'text/xml');
 56+ callback(dom.documentElement);
 57+ } else {
 58+ alert('Failed to parse!');
 59+ }
 60+ });
 61+};
 62+
 63+/**
 64+ * @param {object} tree
 65+ * @param {function(tree, error)} callback
 66+ */
 67+MediaWikiParser.prototype.expandTree = function(tree, callback) {
 68+ // no-op!
 69+ callback(tree, null);
 70+};
 71+
 72+/**
 73+ * Run a preprocessor XML parse tree through the final parser.
 74+ * Since we can't actually ship the XML to MediaWiki, we'll reassemble it
 75+ * and send the text. :P
 76+ *
 77+ * Currently we are not able to map preprocessor nodes to output DOM nodes,
 78+ * so the inspector mode won't work.
 79+ *
 80+ * @param {Node} tree
 81+ * @param {function(domnode, error)} callback
 82+ * @param {HashMap} inspectorMap
 83+ *
 84+ * @fixme use context object for page title
 85+ */
 86+MediaWikiParser.prototype.treeToHtml = function(tree, callback, inspectorMap) {
 87+ var self = this;
 88+ self.treeToSource(tree, function(src, err) {
 89+ if (err) {
 90+ return callback(src, err);
 91+ }
 92+ callApi({
 93+ action: 'parse',
 94+ title: wgPageName,
 95+ text: src,
 96+ prop: 'text',
 97+ pst: 1,
 98+ format: 'json'
 99+ }, function(data, xhr) {
 100+ if (typeof data.parse.text['*'] === 'string') {
 101+ var html = data.parse.text['*'];
 102+ var parsed = $('<div>' + html + '</div>')[0];
 103+ callback(parsed, null);
 104+ } else {
 105+ callback(null, 'Failed to parse!');
 106+ }
 107+ });
 108+ });
 109+};
 110+
 111+
 112+/**
 113+ * Collapse a parse tree back to source, if possible.
 114+ * Ideally should exactly match the original source;
 115+ * at minimum the resulting source should parse into
 116+ * a tree that's identical to the current one.
 117+ *
 118+ * @param {Node} tree
 119+ * @param {function(text, error)} callback
 120+ */
 121+MediaWikiParser.prototype.treeToSource = function(tree, callback) {
 122+ // I forget if this actually works, but let's pretend for now!
 123+ // looks like at least the heads of refs, and templates, need some more tweaking. but close :D
 124+ //var text = $(tree).text();
 125+ //callback(text, null);
 126+
 127+ var collapse, collapseList, collapseChildren;
 128+ collapseList = function(nodes, sep) {
 129+ sep = sep || '';
 130+ var list = $.map(nodes, function(node, i) {
 131+ return collapse(node);
 132+ });
 133+ return list.join(sep);
 134+ };
 135+ collapseChildren = function(nodes, sep) {
 136+ sep = sep || '';
 137+ if (nodes instanceof Node) {
 138+ nodes = [node];
 139+ }
 140+ var list = $.map(nodes, function(node, i) {
 141+ return collapseList(node.childNodes);
 142+ });
 143+ return list.join(sep);
 144+ };
 145+ collapse = function(node) {
 146+ // Based loosely on PPFrame_DOM::expand() in RECOVER_ORIG mode
 147+ var name = node.nodeName || 'string';
 148+ var out, list;
 149+ if (typeof node === 'string') {
 150+ out = node;
 151+ } else if (node.nodeType === Node.TEXT_NODE) {
 152+ out = node.textContent;
 153+ } else if (name === 'root') {
 154+ out = collapseList(node.childNodes);
 155+ } else if (name === 'template') {
 156+ out = '{{' + collapseChildren($(node).children('title,part'), '|') + '}}';
 157+ } else if (name === 'tplarg') {
 158+ out = '{{{' + collapseChildren($(node).children('title,part'), '|') + '}}}';
 159+ } else if (name === 'name') { // temp hack
 160+ out = collapseList(node.childNodes);
 161+ } else if (name === 'value') { // temp hack
 162+ out = collapseList(node.childNodes);
 163+ } else if (name === 'comment') {
 164+ // Recover the literal comment
 165+ out = collapseList(node.childNodes);
 166+ } else if (name === 'ignore') {
 167+ out = collapseList(node.childNodes);
 168+ } else if (name === 'ext') {
 169+ var close = $(node).children('close');
 170+ out = '<' +
 171+ collapseChildren($(node).children('name,attr')) +
 172+ (close.length ? '>' : '/>')+
 173+ collapseChildren($(node).children('inner')) +
 174+ collapseChildren(close);
 175+ } else if (name === 'h') {
 176+ out = $(node).text();
 177+ } else {
 178+ console.log('unrecognized node during expansion', node);
 179+ out = '';
 180+ }
 181+ //console.log(name, node, '->', out);
 182+ return out;
 183+ };
 184+ try {
 185+ var err = null;
 186+ var src = collapse(tree);
 187+ } catch (e) {
 188+ err = e;
 189+ } finally {
 190+ callback(src, err);
 191+ }
 192+};
Property changes on: trunk/extensions/ParserPlayground/modules/ext.parserPlayground.classicParser.js
___________________________________________________________________
Added: svn:eol-style
1193 + native
Index: trunk/extensions/ParserPlayground/modules/lib.pegjs.js
@@ -0,0 +1,4794 @@
 2+/* PEG.js 0.6.1 (http://pegjs.majda.cz/) */
 3+
 4+(function() {
 5+
 6+var undefined;
 7+
 8+var PEG = {
 9+ /* PEG.js version. */
 10+ VERSION: "0.6.1",
 11+
 12+ /*
 13+ * Generates a parser from a specified grammar and returns it.
 14+ *
 15+ * The grammar must be a string in the format described by the metagramar in
 16+ * the parser.pegjs file.
 17+ *
 18+ * Throws |PEG.parser.SyntaxError| if the grammar contains a syntax error or
 19+ * |PEG.GrammarError| if it contains a semantic error. Note that not all
 20+ * errors are detected during the generation and some may protrude to the
 21+ * generated parser and cause its malfunction.
 22+ */
 23+ buildParser: function(grammar) {
 24+ return PEG.compiler.compile(PEG.parser.parse(grammar));
 25+ }
 26+};
 27+
 28+/* Thrown when the grammar contains an error. */
 29+
 30+PEG.GrammarError = function(message) {
 31+ this.name = "PEG.GrammarError";
 32+ this.message = message;
 33+};
 34+
 35+PEG.GrammarError.prototype = Error.prototype;
 36+
 37+function contains(array, value) {
 38+ /*
 39+ * Stupid IE does not have Array.prototype.indexOf, otherwise this function
 40+ * would be a one-liner.
 41+ */
 42+ var length = array.length;
 43+ for (var i = 0; i < length; i++) {
 44+ if (array[i] === value) {
 45+ return true;
 46+ }
 47+ }
 48+ return false;
 49+}
 50+
 51+function each(array, callback) {
 52+ var length = array.length;
 53+ for (var i = 0; i < length; i++) {
 54+ callback(array[i]);
 55+ }
 56+}
 57+
 58+function map(array, callback) {
 59+ var result = [];
 60+ var length = array.length;
 61+ for (var i = 0; i < length; i++) {
 62+ result[i] = callback(array[i]);
 63+ }
 64+ return result;
 65+}
 66+
 67+/*
 68+ * Returns a string padded on the left to a desired length with a character.
 69+ *
 70+ * The code needs to be in sync with th code template in the compilation
 71+ * function for "action" nodes.
 72+ */
 73+function padLeft(input, padding, length) {
 74+ var result = input;
 75+
 76+ var padLength = length - input.length;
 77+ for (var i = 0; i < padLength; i++) {
 78+ result = padding + result;
 79+ }
 80+
 81+ return result;
 82+}
 83+
 84+/*
 85+ * Returns an escape sequence for given character. Uses \x for characters <=
 86+ * 0xFF to save space, \u for the rest.
 87+ *
 88+ * The code needs to be in sync with th code template in the compilation
 89+ * function for "action" nodes.
 90+ */
 91+function escape(ch) {
 92+ var charCode = ch.charCodeAt(0);
 93+
 94+ if (charCode <= 0xFF) {
 95+ var escapeChar = 'x';
 96+ var length = 2;
 97+ } else {
 98+ var escapeChar = 'u';
 99+ var length = 4;
 100+ }
 101+
 102+ return '\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length);
 103+}
 104+
 105+/*
 106+ * Surrounds the string with quotes and escapes characters inside so that the
 107+ * result is a valid JavaScript string.
 108+ *
 109+ * The code needs to be in sync with th code template in the compilation
 110+ * function for "action" nodes.
 111+ */
 112+function quote(s) {
 113+ /*
 114+ * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a string
 115+ * literal except for the closing quote character, backslash, carriage return,
 116+ * line separator, paragraph separator, and line feed. Any character may
 117+ * appear in the form of an escape sequence.
 118+ *
 119+ * For portability, we also escape escape all non-ASCII characters.
 120+ */
 121+ return '"' + s
 122+ .replace(/\\/g, '\\\\') // backslash
 123+ .replace(/"/g, '\\"') // closing quote character
 124+ .replace(/\r/g, '\\r') // carriage return
 125+ .replace(/\n/g, '\\n') // line feed
 126+ .replace(/[\x80-\uFFFF]/g, escape) // non-ASCII characters
 127+ + '"';
 128+};
 129+
 130+/*
 131+ * Escapes characters inside the string so that it can be used as a list of
 132+ * characters in a character class of a regular expression.
 133+ */
 134+function quoteForRegexpClass(s) {
 135+ /*
 136+ * Based on ECMA-262, 5th ed., 7.8.5 & 15.10.1.
 137+ *
 138+ * For portability, we also escape escape all non-ASCII characters.
 139+ */
 140+ return s
 141+ .replace(/\\/g, '\\\\') // backslash
 142+ .replace(/\0/g, '\\0') // null, IE needs this
 143+ .replace(/\//g, '\\/') // closing slash
 144+ .replace(/]/g, '\\]') // closing bracket
 145+ .replace(/-/g, '\\-') // dash
 146+ .replace(/\r/g, '\\r') // carriage return
 147+ .replace(/\n/g, '\\n') // line feed
 148+ .replace(/[\x80-\uFFFF]/g, escape) // non-ASCII characters
 149+}
 150+
 151+/*
 152+ * Builds a node visitor -- a function which takes a node and any number of
 153+ * other parameters, calls an appropriate function according to the node type,
 154+ * passes it all its parameters and returns its value. The functions for various
 155+ * node types are passed in a parameter to |buildNodeVisitor| as a hash.
 156+ */
 157+function buildNodeVisitor(functions) {
 158+ return function(node) {
 159+ return functions[node.type].apply(null, arguments);
 160+ }
 161+}
 162+PEG.parser = (function(){
 163+ /* Generated by PEG.js 0.6.1 (http://pegjs.majda.cz/). */
 164+
 165+ var result = {
 166+ /*
 167+ * Parses the input with a generated parser. If the parsing is successfull,
 168+ * returns a value explicitly or implicitly specified by the grammar from
 169+ * which the parser was generated (see |PEG.buildParser|). If the parsing is
 170+ * unsuccessful, throws |PEG.parser.SyntaxError| describing the error.
 171+ */
 172+ parse: function(input, startRule) {
 173+ var parseFunctions = {
 174+ "__": parse___,
 175+ "action": parse_action,
 176+ "and": parse_and,
 177+ "braced": parse_braced,
 178+ "bracketDelimitedCharacter": parse_bracketDelimitedCharacter,
 179+ "choice": parse_choice,
 180+ "class": parse_class,
 181+ "classCharacter": parse_classCharacter,
 182+ "classCharacterRange": parse_classCharacterRange,
 183+ "colon": parse_colon,
 184+ "comment": parse_comment,
 185+ "digit": parse_digit,
 186+ "dot": parse_dot,
 187+ "doubleQuotedCharacter": parse_doubleQuotedCharacter,
 188+ "doubleQuotedLiteral": parse_doubleQuotedLiteral,
 189+ "eol": parse_eol,
 190+ "eolChar": parse_eolChar,
 191+ "eolEscapeSequence": parse_eolEscapeSequence,
 192+ "equals": parse_equals,
 193+ "grammar": parse_grammar,
 194+ "hexDigit": parse_hexDigit,
 195+ "hexEscapeSequence": parse_hexEscapeSequence,
 196+ "identifier": parse_identifier,
 197+ "initializer": parse_initializer,
 198+ "labeled": parse_labeled,
 199+ "letter": parse_letter,
 200+ "literal": parse_literal,
 201+ "lowerCaseLetter": parse_lowerCaseLetter,
 202+ "lparen": parse_lparen,
 203+ "multiLineComment": parse_multiLineComment,
 204+ "nonBraceCharacter": parse_nonBraceCharacter,
 205+ "nonBraceCharacters": parse_nonBraceCharacters,
 206+ "not": parse_not,
 207+ "plus": parse_plus,
 208+ "prefixed": parse_prefixed,
 209+ "primary": parse_primary,
 210+ "question": parse_question,
 211+ "rparen": parse_rparen,
 212+ "rule": parse_rule,
 213+ "semicolon": parse_semicolon,
 214+ "sequence": parse_sequence,
 215+ "simpleBracketDelimitedCharacter": parse_simpleBracketDelimitedCharacter,
 216+ "simpleDoubleQuotedCharacter": parse_simpleDoubleQuotedCharacter,
 217+ "simpleEscapeSequence": parse_simpleEscapeSequence,
 218+ "simpleSingleQuotedCharacter": parse_simpleSingleQuotedCharacter,
 219+ "singleLineComment": parse_singleLineComment,
 220+ "singleQuotedCharacter": parse_singleQuotedCharacter,
 221+ "singleQuotedLiteral": parse_singleQuotedLiteral,
 222+ "slash": parse_slash,
 223+ "star": parse_star,
 224+ "suffixed": parse_suffixed,
 225+ "unicodeEscapeSequence": parse_unicodeEscapeSequence,
 226+ "upperCaseLetter": parse_upperCaseLetter,
 227+ "whitespace": parse_whitespace,
 228+ "zeroEscapeSequence": parse_zeroEscapeSequence
 229+ };
 230+
 231+ if (startRule !== undefined) {
 232+ if (parseFunctions[startRule] === undefined) {
 233+ throw new Error("Invalid rule name: " + quote(startRule) + ".");
 234+ }
 235+ } else {
 236+ startRule = "grammar";
 237+ }
 238+
 239+ var pos = 0;
 240+ var reportMatchFailures = true;
 241+ var rightmostMatchFailuresPos = 0;
 242+ var rightmostMatchFailuresExpected = [];
 243+ var cache = {};
 244+
 245+ function padLeft(input, padding, length) {
 246+ var result = input;
 247+
 248+ var padLength = length - input.length;
 249+ for (var i = 0; i < padLength; i++) {
 250+ result = padding + result;
 251+ }
 252+
 253+ return result;
 254+ }
 255+
 256+ function escape(ch) {
 257+ var charCode = ch.charCodeAt(0);
 258+
 259+ if (charCode <= 0xFF) {
 260+ var escapeChar = 'x';
 261+ var length = 2;
 262+ } else {
 263+ var escapeChar = 'u';
 264+ var length = 4;
 265+ }
 266+
 267+ return '\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length);
 268+ }
 269+
 270+ function quote(s) {
 271+ /*
 272+ * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a
 273+ * string literal except for the closing quote character, backslash,
 274+ * carriage return, line separator, paragraph separator, and line feed.
 275+ * Any character may appear in the form of an escape sequence.
 276+ */
 277+ return '"' + s
 278+ .replace(/\\/g, '\\\\') // backslash
 279+ .replace(/"/g, '\\"') // closing quote character
 280+ .replace(/\r/g, '\\r') // carriage return
 281+ .replace(/\n/g, '\\n') // line feed
 282+ .replace(/[\x80-\uFFFF]/g, escape) // non-ASCII characters
 283+ + '"';
 284+ }
 285+
 286+ function matchFailed(failure) {
 287+ if (pos < rightmostMatchFailuresPos) {
 288+ return;
 289+ }
 290+
 291+ if (pos > rightmostMatchFailuresPos) {
 292+ rightmostMatchFailuresPos = pos;
 293+ rightmostMatchFailuresExpected = [];
 294+ }
 295+
 296+ rightmostMatchFailuresExpected.push(failure);
 297+ }
 298+
 299+ function parse_grammar() {
 300+ var cacheKey = 'grammar@' + pos;
 301+ var cachedResult = cache[cacheKey];
 302+ if (cachedResult) {
 303+ pos = cachedResult.nextPos;
 304+ return cachedResult.result;
 305+ }
 306+
 307+
 308+ var savedPos0 = pos;
 309+ var result2 = parse___();
 310+ if (result2 !== null) {
 311+ var result6 = parse_initializer();
 312+ var result3 = result6 !== null ? result6 : '';
 313+ if (result3 !== null) {
 314+ var result5 = parse_rule();
 315+ if (result5 !== null) {
 316+ var result4 = [];
 317+ while (result5 !== null) {
 318+ result4.push(result5);
 319+ var result5 = parse_rule();
 320+ }
 321+ } else {
 322+ var result4 = null;
 323+ }
 324+ if (result4 !== null) {
 325+ var result1 = [result2, result3, result4];
 326+ } else {
 327+ var result1 = null;
 328+ pos = savedPos0;
 329+ }
 330+ } else {
 331+ var result1 = null;
 332+ pos = savedPos0;
 333+ }
 334+ } else {
 335+ var result1 = null;
 336+ pos = savedPos0;
 337+ }
 338+ var result0 = result1 !== null
 339+ ? (function(initializer, rules) {
 340+ var rulesConverted = {};
 341+ each(rules, function(rule) { rulesConverted[rule.name] = rule; });
 342+
 343+ return {
 344+ type: "grammar",
 345+ initializer: initializer !== "" ? initializer : null,
 346+ rules: rulesConverted,
 347+ startRule: rules[0].name
 348+ }
 349+ })(result1[1], result1[2])
 350+ : null;
 351+
 352+
 353+
 354+ cache[cacheKey] = {
 355+ nextPos: pos,
 356+ result: result0
 357+ };
 358+ return result0;
 359+ }
 360+
 361+ function parse_initializer() {
 362+ var cacheKey = 'initializer@' + pos;
 363+ var cachedResult = cache[cacheKey];
 364+ if (cachedResult) {
 365+ pos = cachedResult.nextPos;
 366+ return cachedResult.result;
 367+ }
 368+
 369+
 370+ var savedPos0 = pos;
 371+ var result2 = parse_action();
 372+ if (result2 !== null) {
 373+ var result4 = parse_semicolon();
 374+ var result3 = result4 !== null ? result4 : '';
 375+ if (result3 !== null) {
 376+ var result1 = [result2, result3];
 377+ } else {
 378+ var result1 = null;
 379+ pos = savedPos0;
 380+ }
 381+ } else {
 382+ var result1 = null;
 383+ pos = savedPos0;
 384+ }
 385+ var result0 = result1 !== null
 386+ ? (function(code) {
 387+ return {
 388+ type: "initializer",
 389+ code: code
 390+ };
 391+ })(result1[0])
 392+ : null;
 393+
 394+
 395+
 396+ cache[cacheKey] = {
 397+ nextPos: pos,
 398+ result: result0
 399+ };
 400+ return result0;
 401+ }
 402+
 403+ function parse_rule() {
 404+ var cacheKey = 'rule@' + pos;
 405+ var cachedResult = cache[cacheKey];
 406+ if (cachedResult) {
 407+ pos = cachedResult.nextPos;
 408+ return cachedResult.result;
 409+ }
 410+
 411+
 412+ var savedPos0 = pos;
 413+ var result2 = parse_identifier();
 414+ if (result2 !== null) {
 415+ var result9 = parse_literal();
 416+ if (result9 !== null) {
 417+ var result3 = result9;
 418+ } else {
 419+ if (input.substr(pos, 0) === "") {
 420+ var result8 = "";
 421+ pos += 0;
 422+ } else {
 423+ var result8 = null;
 424+ if (reportMatchFailures) {
 425+ matchFailed("\"\"");
 426+ }
 427+ }
 428+ if (result8 !== null) {
 429+ var result3 = result8;
 430+ } else {
 431+ var result3 = null;;
 432+ };
 433+ }
 434+ if (result3 !== null) {
 435+ var result4 = parse_equals();
 436+ if (result4 !== null) {
 437+ var result5 = parse_choice();
 438+ if (result5 !== null) {
 439+ var result7 = parse_semicolon();
 440+ var result6 = result7 !== null ? result7 : '';
 441+ if (result6 !== null) {
 442+ var result1 = [result2, result3, result4, result5, result6];
 443+ } else {
 444+ var result1 = null;
 445+ pos = savedPos0;
 446+ }
 447+ } else {
 448+ var result1 = null;
 449+ pos = savedPos0;
 450+ }
 451+ } else {
 452+ var result1 = null;
 453+ pos = savedPos0;
 454+ }
 455+ } else {
 456+ var result1 = null;
 457+ pos = savedPos0;
 458+ }
 459+ } else {
 460+ var result1 = null;
 461+ pos = savedPos0;
 462+ }
 463+ var result0 = result1 !== null
 464+ ? (function(name, displayName, expression) {
 465+ return {
 466+ type: "rule",
 467+ name: name,
 468+ displayName: displayName !== "" ? displayName : null,
 469+ expression: expression
 470+ };
 471+ })(result1[0], result1[1], result1[3])
 472+ : null;
 473+
 474+
 475+
 476+ cache[cacheKey] = {
 477+ nextPos: pos,
 478+ result: result0
 479+ };
 480+ return result0;
 481+ }
 482+
 483+ function parse_choice() {
 484+ var cacheKey = 'choice@' + pos;
 485+ var cachedResult = cache[cacheKey];
 486+ if (cachedResult) {
 487+ pos = cachedResult.nextPos;
 488+ return cachedResult.result;
 489+ }
 490+
 491+
 492+ var savedPos0 = pos;
 493+ var result2 = parse_sequence();
 494+ if (result2 !== null) {
 495+ var result3 = [];
 496+ var savedPos1 = pos;
 497+ var result5 = parse_slash();
 498+ if (result5 !== null) {
 499+ var result6 = parse_sequence();
 500+ if (result6 !== null) {
 501+ var result4 = [result5, result6];
 502+ } else {
 503+ var result4 = null;
 504+ pos = savedPos1;
 505+ }
 506+ } else {
 507+ var result4 = null;
 508+ pos = savedPos1;
 509+ }
 510+ while (result4 !== null) {
 511+ result3.push(result4);
 512+ var savedPos1 = pos;
 513+ var result5 = parse_slash();
 514+ if (result5 !== null) {
 515+ var result6 = parse_sequence();
 516+ if (result6 !== null) {
 517+ var result4 = [result5, result6];
 518+ } else {
 519+ var result4 = null;
 520+ pos = savedPos1;
 521+ }
 522+ } else {
 523+ var result4 = null;
 524+ pos = savedPos1;
 525+ }
 526+ }
 527+ if (result3 !== null) {
 528+ var result1 = [result2, result3];
 529+ } else {
 530+ var result1 = null;
 531+ pos = savedPos0;
 532+ }
 533+ } else {
 534+ var result1 = null;
 535+ pos = savedPos0;
 536+ }
 537+ var result0 = result1 !== null
 538+ ? (function(head, tail) {
 539+ if (tail.length > 0) {
 540+ var alternatives = [head].concat(map(
 541+ tail,
 542+ function(element) { return element[1]; }
 543+ ));
 544+ return {
 545+ type: "choice",
 546+ alternatives: alternatives
 547+ }
 548+ } else {
 549+ return head;
 550+ }
 551+ })(result1[0], result1[1])
 552+ : null;
 553+
 554+
 555+
 556+ cache[cacheKey] = {
 557+ nextPos: pos,
 558+ result: result0
 559+ };
 560+ return result0;
 561+ }
 562+
 563+ function parse_sequence() {
 564+ var cacheKey = 'sequence@' + pos;
 565+ var cachedResult = cache[cacheKey];
 566+ if (cachedResult) {
 567+ pos = cachedResult.nextPos;
 568+ return cachedResult.result;
 569+ }
 570+
 571+
 572+ var savedPos0 = pos;
 573+ var result6 = [];
 574+ var result8 = parse_labeled();
 575+ while (result8 !== null) {
 576+ result6.push(result8);
 577+ var result8 = parse_labeled();
 578+ }
 579+ if (result6 !== null) {
 580+ var result7 = parse_action();
 581+ if (result7 !== null) {
 582+ var result5 = [result6, result7];
 583+ } else {
 584+ var result5 = null;
 585+ pos = savedPos0;
 586+ }
 587+ } else {
 588+ var result5 = null;
 589+ pos = savedPos0;
 590+ }
 591+ var result4 = result5 !== null
 592+ ? (function(elements, code) {
 593+ var expression = elements.length != 1
 594+ ? {
 595+ type: "sequence",
 596+ elements: elements
 597+ }
 598+ : elements[0];
 599+ return {
 600+ type: "action",
 601+ expression: expression,
 602+ code: code
 603+ };
 604+ })(result5[0], result5[1])
 605+ : null;
 606+ if (result4 !== null) {
 607+ var result0 = result4;
 608+ } else {
 609+ var result2 = [];
 610+ var result3 = parse_labeled();
 611+ while (result3 !== null) {
 612+ result2.push(result3);
 613+ var result3 = parse_labeled();
 614+ }
 615+ var result1 = result2 !== null
 616+ ? (function(elements) {
 617+ return elements.length != 1
 618+ ? {
 619+ type: "sequence",
 620+ elements: elements
 621+ }
 622+ : elements[0];
 623+ })(result2)
 624+ : null;
 625+ if (result1 !== null) {
 626+ var result0 = result1;
 627+ } else {
 628+ var result0 = null;;
 629+ };
 630+ }
 631+
 632+
 633+
 634+ cache[cacheKey] = {
 635+ nextPos: pos,
 636+ result: result0
 637+ };
 638+ return result0;
 639+ }
 640+
 641+ function parse_labeled() {
 642+ var cacheKey = 'labeled@' + pos;
 643+ var cachedResult = cache[cacheKey];
 644+ if (cachedResult) {
 645+ pos = cachedResult.nextPos;
 646+ return cachedResult.result;
 647+ }
 648+
 649+
 650+ var savedPos0 = pos;
 651+ var result4 = parse_identifier();
 652+ if (result4 !== null) {
 653+ var result5 = parse_colon();
 654+ if (result5 !== null) {
 655+ var result6 = parse_prefixed();
 656+ if (result6 !== null) {
 657+ var result3 = [result4, result5, result6];
 658+ } else {
 659+ var result3 = null;
 660+ pos = savedPos0;
 661+ }
 662+ } else {
 663+ var result3 = null;
 664+ pos = savedPos0;
 665+ }
 666+ } else {
 667+ var result3 = null;
 668+ pos = savedPos0;
 669+ }
 670+ var result2 = result3 !== null
 671+ ? (function(label, expression) {
 672+ return {
 673+ type: "labeled",
 674+ label: label,
 675+ expression: expression
 676+ };
 677+ })(result3[0], result3[2])
 678+ : null;
 679+ if (result2 !== null) {
 680+ var result0 = result2;
 681+ } else {
 682+ var result1 = parse_prefixed();
 683+ if (result1 !== null) {
 684+ var result0 = result1;
 685+ } else {
 686+ var result0 = null;;
 687+ };
 688+ }
 689+
 690+
 691+
 692+ cache[cacheKey] = {
 693+ nextPos: pos,
 694+ result: result0
 695+ };
 696+ return result0;
 697+ }
 698+
 699+ function parse_prefixed() {
 700+ var cacheKey = 'prefixed@' + pos;
 701+ var cachedResult = cache[cacheKey];
 702+ if (cachedResult) {
 703+ pos = cachedResult.nextPos;
 704+ return cachedResult.result;
 705+ }
 706+
 707+
 708+ var savedPos3 = pos;
 709+ var result16 = parse_and();
 710+ if (result16 !== null) {
 711+ var result17 = parse_action();
 712+ if (result17 !== null) {
 713+ var result15 = [result16, result17];
 714+ } else {
 715+ var result15 = null;
 716+ pos = savedPos3;
 717+ }
 718+ } else {
 719+ var result15 = null;
 720+ pos = savedPos3;
 721+ }
 722+ var result14 = result15 !== null
 723+ ? (function(code) {
 724+ return {
 725+ type: "semantic_and",
 726+ code: code
 727+ };
 728+ })(result15[1])
 729+ : null;
 730+ if (result14 !== null) {
 731+ var result0 = result14;
 732+ } else {
 733+ var savedPos2 = pos;
 734+ var result12 = parse_and();
 735+ if (result12 !== null) {
 736+ var result13 = parse_suffixed();
 737+ if (result13 !== null) {
 738+ var result11 = [result12, result13];
 739+ } else {
 740+ var result11 = null;
 741+ pos = savedPos2;
 742+ }
 743+ } else {
 744+ var result11 = null;
 745+ pos = savedPos2;
 746+ }
 747+ var result10 = result11 !== null
 748+ ? (function(expression) {
 749+ return {
 750+ type: "simple_and",
 751+ expression: expression
 752+ };
 753+ })(result11[1])
 754+ : null;
 755+ if (result10 !== null) {
 756+ var result0 = result10;
 757+ } else {
 758+ var savedPos1 = pos;
 759+ var result8 = parse_not();
 760+ if (result8 !== null) {
 761+ var result9 = parse_action();
 762+ if (result9 !== null) {
 763+ var result7 = [result8, result9];
 764+ } else {
 765+ var result7 = null;
 766+ pos = savedPos1;
 767+ }
 768+ } else {
 769+ var result7 = null;
 770+ pos = savedPos1;
 771+ }
 772+ var result6 = result7 !== null
 773+ ? (function(code) {
 774+ return {
 775+ type: "semantic_not",
 776+ code: code
 777+ };
 778+ })(result7[1])
 779+ : null;
 780+ if (result6 !== null) {
 781+ var result0 = result6;
 782+ } else {
 783+ var savedPos0 = pos;
 784+ var result4 = parse_not();
 785+ if (result4 !== null) {
 786+ var result5 = parse_suffixed();
 787+ if (result5 !== null) {
 788+ var result3 = [result4, result5];
 789+ } else {
 790+ var result3 = null;
 791+ pos = savedPos0;
 792+ }
 793+ } else {
 794+ var result3 = null;
 795+ pos = savedPos0;
 796+ }
 797+ var result2 = result3 !== null
 798+ ? (function(expression) {
 799+ return {
 800+ type: "simple_not",
 801+ expression: expression
 802+ };
 803+ })(result3[1])
 804+ : null;
 805+ if (result2 !== null) {
 806+ var result0 = result2;
 807+ } else {
 808+ var result1 = parse_suffixed();
 809+ if (result1 !== null) {
 810+ var result0 = result1;
 811+ } else {
 812+ var result0 = null;;
 813+ };
 814+ };
 815+ };
 816+ };
 817+ }
 818+
 819+
 820+
 821+ cache[cacheKey] = {
 822+ nextPos: pos,
 823+ result: result0
 824+ };
 825+ return result0;
 826+ }
 827+
 828+ function parse_suffixed() {
 829+ var cacheKey = 'suffixed@' + pos;
 830+ var cachedResult = cache[cacheKey];
 831+ if (cachedResult) {
 832+ pos = cachedResult.nextPos;
 833+ return cachedResult.result;
 834+ }
 835+
 836+
 837+ var savedPos2 = pos;
 838+ var result12 = parse_primary();
 839+ if (result12 !== null) {
 840+ var result13 = parse_question();
 841+ if (result13 !== null) {
 842+ var result11 = [result12, result13];
 843+ } else {
 844+ var result11 = null;
 845+ pos = savedPos2;
 846+ }
 847+ } else {
 848+ var result11 = null;
 849+ pos = savedPos2;
 850+ }
 851+ var result10 = result11 !== null
 852+ ? (function(expression) {
 853+ return {
 854+ type: "optional",
 855+ expression: expression
 856+ };
 857+ })(result11[0])
 858+ : null;
 859+ if (result10 !== null) {
 860+ var result0 = result10;
 861+ } else {
 862+ var savedPos1 = pos;
 863+ var result8 = parse_primary();
 864+ if (result8 !== null) {
 865+ var result9 = parse_star();
 866+ if (result9 !== null) {
 867+ var result7 = [result8, result9];
 868+ } else {
 869+ var result7 = null;
 870+ pos = savedPos1;
 871+ }
 872+ } else {
 873+ var result7 = null;
 874+ pos = savedPos1;
 875+ }
 876+ var result6 = result7 !== null
 877+ ? (function(expression) {
 878+ return {
 879+ type: "zero_or_more",
 880+ expression: expression
 881+ };
 882+ })(result7[0])
 883+ : null;
 884+ if (result6 !== null) {
 885+ var result0 = result6;
 886+ } else {
 887+ var savedPos0 = pos;
 888+ var result4 = parse_primary();
 889+ if (result4 !== null) {
 890+ var result5 = parse_plus();
 891+ if (result5 !== null) {
 892+ var result3 = [result4, result5];
 893+ } else {
 894+ var result3 = null;
 895+ pos = savedPos0;
 896+ }
 897+ } else {
 898+ var result3 = null;
 899+ pos = savedPos0;
 900+ }
 901+ var result2 = result3 !== null
 902+ ? (function(expression) {
 903+ return {
 904+ type: "one_or_more",
 905+ expression: expression
 906+ };
 907+ })(result3[0])
 908+ : null;
 909+ if (result2 !== null) {
 910+ var result0 = result2;
 911+ } else {
 912+ var result1 = parse_primary();
 913+ if (result1 !== null) {
 914+ var result0 = result1;
 915+ } else {
 916+ var result0 = null;;
 917+ };
 918+ };
 919+ };
 920+ }
 921+
 922+
 923+
 924+ cache[cacheKey] = {
 925+ nextPos: pos,
 926+ result: result0
 927+ };
 928+ return result0;
 929+ }
 930+
 931+ function parse_primary() {
 932+ var cacheKey = 'primary@' + pos;
 933+ var cachedResult = cache[cacheKey];
 934+ if (cachedResult) {
 935+ pos = cachedResult.nextPos;
 936+ return cachedResult.result;
 937+ }
 938+
 939+
 940+ var savedPos1 = pos;
 941+ var result13 = parse_identifier();
 942+ if (result13 !== null) {
 943+ var savedPos2 = pos;
 944+ var savedReportMatchFailuresVar0 = reportMatchFailures;
 945+ reportMatchFailures = false;
 946+ var savedPos3 = pos;
 947+ var result19 = parse_literal();
 948+ if (result19 !== null) {
 949+ var result16 = result19;
 950+ } else {
 951+ if (input.substr(pos, 0) === "") {
 952+ var result18 = "";
 953+ pos += 0;
 954+ } else {
 955+ var result18 = null;
 956+ if (reportMatchFailures) {
 957+ matchFailed("\"\"");
 958+ }
 959+ }
 960+ if (result18 !== null) {
 961+ var result16 = result18;
 962+ } else {
 963+ var result16 = null;;
 964+ };
 965+ }
 966+ if (result16 !== null) {
 967+ var result17 = parse_equals();
 968+ if (result17 !== null) {
 969+ var result15 = [result16, result17];
 970+ } else {
 971+ var result15 = null;
 972+ pos = savedPos3;
 973+ }
 974+ } else {
 975+ var result15 = null;
 976+ pos = savedPos3;
 977+ }
 978+ reportMatchFailures = savedReportMatchFailuresVar0;
 979+ if (result15 === null) {
 980+ var result14 = '';
 981+ } else {
 982+ var result14 = null;
 983+ pos = savedPos2;
 984+ }
 985+ if (result14 !== null) {
 986+ var result12 = [result13, result14];
 987+ } else {
 988+ var result12 = null;
 989+ pos = savedPos1;
 990+ }
 991+ } else {
 992+ var result12 = null;
 993+ pos = savedPos1;
 994+ }
 995+ var result11 = result12 !== null
 996+ ? (function(name) {
 997+ return {
 998+ type: "rule_ref",
 999+ name: name
 1000+ };
 1001+ })(result12[0])
 1002+ : null;
 1003+ if (result11 !== null) {
 1004+ var result0 = result11;
 1005+ } else {
 1006+ var result10 = parse_literal();
 1007+ var result9 = result10 !== null
 1008+ ? (function(value) {
 1009+ return {
 1010+ type: "literal",
 1011+ value: value
 1012+ };
 1013+ })(result10)
 1014+ : null;
 1015+ if (result9 !== null) {
 1016+ var result0 = result9;
 1017+ } else {
 1018+ var result8 = parse_dot();
 1019+ var result7 = result8 !== null
 1020+ ? (function() { return { type: "any" }; })()
 1021+ : null;
 1022+ if (result7 !== null) {
 1023+ var result0 = result7;
 1024+ } else {
 1025+ var result6 = parse_class();
 1026+ if (result6 !== null) {
 1027+ var result0 = result6;
 1028+ } else {
 1029+ var savedPos0 = pos;
 1030+ var result3 = parse_lparen();
 1031+ if (result3 !== null) {
 1032+ var result4 = parse_choice();
 1033+ if (result4 !== null) {
 1034+ var result5 = parse_rparen();
 1035+ if (result5 !== null) {
 1036+ var result2 = [result3, result4, result5];
 1037+ } else {
 1038+ var result2 = null;
 1039+ pos = savedPos0;
 1040+ }
 1041+ } else {
 1042+ var result2 = null;
 1043+ pos = savedPos0;
 1044+ }
 1045+ } else {
 1046+ var result2 = null;
 1047+ pos = savedPos0;
 1048+ }
 1049+ var result1 = result2 !== null
 1050+ ? (function(expression) { return expression; })(result2[1])
 1051+ : null;
 1052+ if (result1 !== null) {
 1053+ var result0 = result1;
 1054+ } else {
 1055+ var result0 = null;;
 1056+ };
 1057+ };
 1058+ };
 1059+ };
 1060+ }
 1061+
 1062+
 1063+
 1064+ cache[cacheKey] = {
 1065+ nextPos: pos,
 1066+ result: result0
 1067+ };
 1068+ return result0;
 1069+ }
 1070+
 1071+ function parse_action() {
 1072+ var cacheKey = 'action@' + pos;
 1073+ var cachedResult = cache[cacheKey];
 1074+ if (cachedResult) {
 1075+ pos = cachedResult.nextPos;
 1076+ return cachedResult.result;
 1077+ }
 1078+
 1079+ var savedReportMatchFailures = reportMatchFailures;
 1080+ reportMatchFailures = false;
 1081+ var savedPos0 = pos;
 1082+ var result2 = parse_braced();
 1083+ if (result2 !== null) {
 1084+ var result3 = parse___();
 1085+ if (result3 !== null) {
 1086+ var result1 = [result2, result3];
 1087+ } else {
 1088+ var result1 = null;
 1089+ pos = savedPos0;
 1090+ }
 1091+ } else {
 1092+ var result1 = null;
 1093+ pos = savedPos0;
 1094+ }
 1095+ var result0 = result1 !== null
 1096+ ? (function(braced) { return braced.substr(1, braced.length - 2); })(result1[0])
 1097+ : null;
 1098+ reportMatchFailures = savedReportMatchFailures;
 1099+ if (reportMatchFailures && result0 === null) {
 1100+ matchFailed("action");
 1101+ }
 1102+
 1103+ cache[cacheKey] = {
 1104+ nextPos: pos,
 1105+ result: result0
 1106+ };
 1107+ return result0;
 1108+ }
 1109+
 1110+ function parse_braced() {
 1111+ var cacheKey = 'braced@' + pos;
 1112+ var cachedResult = cache[cacheKey];
 1113+ if (cachedResult) {
 1114+ pos = cachedResult.nextPos;
 1115+ return cachedResult.result;
 1116+ }
 1117+
 1118+
 1119+ var savedPos0 = pos;
 1120+ if (input.substr(pos, 1) === "{") {
 1121+ var result2 = "{";
 1122+ pos += 1;
 1123+ } else {
 1124+ var result2 = null;
 1125+ if (reportMatchFailures) {
 1126+ matchFailed("\"{\"");
 1127+ }
 1128+ }
 1129+ if (result2 !== null) {
 1130+ var result3 = [];
 1131+ var result7 = parse_braced();
 1132+ if (result7 !== null) {
 1133+ var result5 = result7;
 1134+ } else {
 1135+ var result6 = parse_nonBraceCharacter();
 1136+ if (result6 !== null) {
 1137+ var result5 = result6;
 1138+ } else {
 1139+ var result5 = null;;
 1140+ };
 1141+ }
 1142+ while (result5 !== null) {
 1143+ result3.push(result5);
 1144+ var result7 = parse_braced();
 1145+ if (result7 !== null) {
 1146+ var result5 = result7;
 1147+ } else {
 1148+ var result6 = parse_nonBraceCharacter();
 1149+ if (result6 !== null) {
 1150+ var result5 = result6;
 1151+ } else {
 1152+ var result5 = null;;
 1153+ };
 1154+ }
 1155+ }
 1156+ if (result3 !== null) {
 1157+ if (input.substr(pos, 1) === "}") {
 1158+ var result4 = "}";
 1159+ pos += 1;
 1160+ } else {
 1161+ var result4 = null;
 1162+ if (reportMatchFailures) {
 1163+ matchFailed("\"}\"");
 1164+ }
 1165+ }
 1166+ if (result4 !== null) {
 1167+ var result1 = [result2, result3, result4];
 1168+ } else {
 1169+ var result1 = null;
 1170+ pos = savedPos0;
 1171+ }
 1172+ } else {
 1173+ var result1 = null;
 1174+ pos = savedPos0;
 1175+ }
 1176+ } else {
 1177+ var result1 = null;
 1178+ pos = savedPos0;
 1179+ }
 1180+ var result0 = result1 !== null
 1181+ ? (function(parts) {
 1182+ return "{" + parts.join("") + "}";
 1183+ })(result1[1])
 1184+ : null;
 1185+
 1186+
 1187+
 1188+ cache[cacheKey] = {
 1189+ nextPos: pos,
 1190+ result: result0
 1191+ };
 1192+ return result0;
 1193+ }
 1194+
 1195+ function parse_nonBraceCharacters() {
 1196+ var cacheKey = 'nonBraceCharacters@' + pos;
 1197+ var cachedResult = cache[cacheKey];
 1198+ if (cachedResult) {
 1199+ pos = cachedResult.nextPos;
 1200+ return cachedResult.result;
 1201+ }
 1202+
 1203+
 1204+ var result2 = parse_nonBraceCharacter();
 1205+ if (result2 !== null) {
 1206+ var result1 = [];
 1207+ while (result2 !== null) {
 1208+ result1.push(result2);
 1209+ var result2 = parse_nonBraceCharacter();
 1210+ }
 1211+ } else {
 1212+ var result1 = null;
 1213+ }
 1214+ var result0 = result1 !== null
 1215+ ? (function(chars) { return chars.join(""); })(result1)
 1216+ : null;
 1217+
 1218+
 1219+
 1220+ cache[cacheKey] = {
 1221+ nextPos: pos,
 1222+ result: result0
 1223+ };
 1224+ return result0;
 1225+ }
 1226+
 1227+ function parse_nonBraceCharacter() {
 1228+ var cacheKey = 'nonBraceCharacter@' + pos;
 1229+ var cachedResult = cache[cacheKey];
 1230+ if (cachedResult) {
 1231+ pos = cachedResult.nextPos;
 1232+ return cachedResult.result;
 1233+ }
 1234+
 1235+
 1236+ if (input.substr(pos).match(/^[^{}]/) !== null) {
 1237+ var result0 = input.charAt(pos);
 1238+ pos++;
 1239+ } else {
 1240+ var result0 = null;
 1241+ if (reportMatchFailures) {
 1242+ matchFailed("[^{}]");
 1243+ }
 1244+ }
 1245+
 1246+
 1247+
 1248+ cache[cacheKey] = {
 1249+ nextPos: pos,
 1250+ result: result0
 1251+ };
 1252+ return result0;
 1253+ }
 1254+
 1255+ function parse_equals() {
 1256+ var cacheKey = 'equals@' + pos;
 1257+ var cachedResult = cache[cacheKey];
 1258+ if (cachedResult) {
 1259+ pos = cachedResult.nextPos;
 1260+ return cachedResult.result;
 1261+ }
 1262+
 1263+
 1264+ var savedPos0 = pos;
 1265+ if (input.substr(pos, 1) === "=") {
 1266+ var result2 = "=";
 1267+ pos += 1;
 1268+ } else {
 1269+ var result2 = null;
 1270+ if (reportMatchFailures) {
 1271+ matchFailed("\"=\"");
 1272+ }
 1273+ }
 1274+ if (result2 !== null) {
 1275+ var result3 = parse___();
 1276+ if (result3 !== null) {
 1277+ var result1 = [result2, result3];
 1278+ } else {
 1279+ var result1 = null;
 1280+ pos = savedPos0;
 1281+ }
 1282+ } else {
 1283+ var result1 = null;
 1284+ pos = savedPos0;
 1285+ }
 1286+ var result0 = result1 !== null
 1287+ ? (function() { return "="; })()
 1288+ : null;
 1289+
 1290+
 1291+
 1292+ cache[cacheKey] = {
 1293+ nextPos: pos,
 1294+ result: result0
 1295+ };
 1296+ return result0;
 1297+ }
 1298+
 1299+ function parse_colon() {
 1300+ var cacheKey = 'colon@' + pos;
 1301+ var cachedResult = cache[cacheKey];
 1302+ if (cachedResult) {
 1303+ pos = cachedResult.nextPos;
 1304+ return cachedResult.result;
 1305+ }
 1306+
 1307+
 1308+ var savedPos0 = pos;
 1309+ if (input.substr(pos, 1) === ":") {
 1310+ var result2 = ":";
 1311+ pos += 1;
 1312+ } else {
 1313+ var result2 = null;
 1314+ if (reportMatchFailures) {
 1315+ matchFailed("\":\"");
 1316+ }
 1317+ }
 1318+ if (result2 !== null) {
 1319+ var result3 = parse___();
 1320+ if (result3 !== null) {
 1321+ var result1 = [result2, result3];
 1322+ } else {
 1323+ var result1 = null;
 1324+ pos = savedPos0;
 1325+ }
 1326+ } else {
 1327+ var result1 = null;
 1328+ pos = savedPos0;
 1329+ }
 1330+ var result0 = result1 !== null
 1331+ ? (function() { return ":"; })()
 1332+ : null;
 1333+
 1334+
 1335+
 1336+ cache[cacheKey] = {
 1337+ nextPos: pos,
 1338+ result: result0
 1339+ };
 1340+ return result0;
 1341+ }
 1342+
 1343+ function parse_semicolon() {
 1344+ var cacheKey = 'semicolon@' + pos;
 1345+ var cachedResult = cache[cacheKey];
 1346+ if (cachedResult) {
 1347+ pos = cachedResult.nextPos;
 1348+ return cachedResult.result;
 1349+ }
 1350+
 1351+
 1352+ var savedPos0 = pos;
 1353+ if (input.substr(pos, 1) === ";") {
 1354+ var result2 = ";";
 1355+ pos += 1;
 1356+ } else {
 1357+ var result2 = null;
 1358+ if (reportMatchFailures) {
 1359+ matchFailed("\";\"");
 1360+ }
 1361+ }
 1362+ if (result2 !== null) {
 1363+ var result3 = parse___();
 1364+ if (result3 !== null) {
 1365+ var result1 = [result2, result3];
 1366+ } else {
 1367+ var result1 = null;
 1368+ pos = savedPos0;
 1369+ }
 1370+ } else {
 1371+ var result1 = null;
 1372+ pos = savedPos0;
 1373+ }
 1374+ var result0 = result1 !== null
 1375+ ? (function() { return ";"; })()
 1376+ : null;
 1377+
 1378+
 1379+
 1380+ cache[cacheKey] = {
 1381+ nextPos: pos,
 1382+ result: result0
 1383+ };
 1384+ return result0;
 1385+ }
 1386+
 1387+ function parse_slash() {
 1388+ var cacheKey = 'slash@' + pos;
 1389+ var cachedResult = cache[cacheKey];
 1390+ if (cachedResult) {
 1391+ pos = cachedResult.nextPos;
 1392+ return cachedResult.result;
 1393+ }
 1394+
 1395+
 1396+ var savedPos0 = pos;
 1397+ if (input.substr(pos, 1) === "/") {
 1398+ var result2 = "/";
 1399+ pos += 1;
 1400+ } else {
 1401+ var result2 = null;
 1402+ if (reportMatchFailures) {
 1403+ matchFailed("\"/\"");
 1404+ }
 1405+ }
 1406+ if (result2 !== null) {
 1407+ var result3 = parse___();
 1408+ if (result3 !== null) {
 1409+ var result1 = [result2, result3];
 1410+ } else {
 1411+ var result1 = null;
 1412+ pos = savedPos0;
 1413+ }
 1414+ } else {
 1415+ var result1 = null;
 1416+ pos = savedPos0;
 1417+ }
 1418+ var result0 = result1 !== null
 1419+ ? (function() { return "/"; })()
 1420+ : null;
 1421+
 1422+
 1423+
 1424+ cache[cacheKey] = {
 1425+ nextPos: pos,
 1426+ result: result0
 1427+ };
 1428+ return result0;
 1429+ }
 1430+
 1431+ function parse_and() {
 1432+ var cacheKey = 'and@' + pos;
 1433+ var cachedResult = cache[cacheKey];
 1434+ if (cachedResult) {
 1435+ pos = cachedResult.nextPos;
 1436+ return cachedResult.result;
 1437+ }
 1438+
 1439+
 1440+ var savedPos0 = pos;
 1441+ if (input.substr(pos, 1) === "&") {
 1442+ var result2 = "&";
 1443+ pos += 1;
 1444+ } else {
 1445+ var result2 = null;
 1446+ if (reportMatchFailures) {
 1447+ matchFailed("\"&\"");
 1448+ }
 1449+ }
 1450+ if (result2 !== null) {
 1451+ var result3 = parse___();
 1452+ if (result3 !== null) {
 1453+ var result1 = [result2, result3];
 1454+ } else {
 1455+ var result1 = null;
 1456+ pos = savedPos0;
 1457+ }
 1458+ } else {
 1459+ var result1 = null;
 1460+ pos = savedPos0;
 1461+ }
 1462+ var result0 = result1 !== null
 1463+ ? (function() { return "&"; })()
 1464+ : null;
 1465+
 1466+
 1467+
 1468+ cache[cacheKey] = {
 1469+ nextPos: pos,
 1470+ result: result0
 1471+ };
 1472+ return result0;
 1473+ }
 1474+
 1475+ function parse_not() {
 1476+ var cacheKey = 'not@' + pos;
 1477+ var cachedResult = cache[cacheKey];
 1478+ if (cachedResult) {
 1479+ pos = cachedResult.nextPos;
 1480+ return cachedResult.result;
 1481+ }
 1482+
 1483+
 1484+ var savedPos0 = pos;
 1485+ if (input.substr(pos, 1) === "!") {
 1486+ var result2 = "!";
 1487+ pos += 1;
 1488+ } else {
 1489+ var result2 = null;
 1490+ if (reportMatchFailures) {
 1491+ matchFailed("\"!\"");
 1492+ }
 1493+ }
 1494+ if (result2 !== null) {
 1495+ var result3 = parse___();
 1496+ if (result3 !== null) {
 1497+ var result1 = [result2, result3];
 1498+ } else {
 1499+ var result1 = null;
 1500+ pos = savedPos0;
 1501+ }
 1502+ } else {
 1503+ var result1 = null;
 1504+ pos = savedPos0;
 1505+ }
 1506+ var result0 = result1 !== null
 1507+ ? (function() { return "!"; })()
 1508+ : null;
 1509+
 1510+
 1511+
 1512+ cache[cacheKey] = {
 1513+ nextPos: pos,
 1514+ result: result0
 1515+ };
 1516+ return result0;
 1517+ }
 1518+
 1519+ function parse_question() {
 1520+ var cacheKey = 'question@' + pos;
 1521+ var cachedResult = cache[cacheKey];
 1522+ if (cachedResult) {
 1523+ pos = cachedResult.nextPos;
 1524+ return cachedResult.result;
 1525+ }
 1526+
 1527+
 1528+ var savedPos0 = pos;
 1529+ if (input.substr(pos, 1) === "?") {
 1530+ var result2 = "?";
 1531+ pos += 1;
 1532+ } else {
 1533+ var result2 = null;
 1534+ if (reportMatchFailures) {
 1535+ matchFailed("\"?\"");
 1536+ }
 1537+ }
 1538+ if (result2 !== null) {
 1539+ var result3 = parse___();
 1540+ if (result3 !== null) {
 1541+ var result1 = [result2, result3];
 1542+ } else {
 1543+ var result1 = null;
 1544+ pos = savedPos0;
 1545+ }
 1546+ } else {
 1547+ var result1 = null;
 1548+ pos = savedPos0;
 1549+ }
 1550+ var result0 = result1 !== null
 1551+ ? (function() { return "?"; })()
 1552+ : null;
 1553+
 1554+
 1555+
 1556+ cache[cacheKey] = {
 1557+ nextPos: pos,
 1558+ result: result0
 1559+ };
 1560+ return result0;
 1561+ }
 1562+
 1563+ function parse_star() {
 1564+ var cacheKey = 'star@' + pos;
 1565+ var cachedResult = cache[cacheKey];
 1566+ if (cachedResult) {
 1567+ pos = cachedResult.nextPos;
 1568+ return cachedResult.result;
 1569+ }
 1570+
 1571+
 1572+ var savedPos0 = pos;
 1573+ if (input.substr(pos, 1) === "*") {
 1574+ var result2 = "*";
 1575+ pos += 1;
 1576+ } else {
 1577+ var result2 = null;
 1578+ if (reportMatchFailures) {
 1579+ matchFailed("\"*\"");
 1580+ }
 1581+ }
 1582+ if (result2 !== null) {
 1583+ var result3 = parse___();
 1584+ if (result3 !== null) {
 1585+ var result1 = [result2, result3];
 1586+ } else {
 1587+ var result1 = null;
 1588+ pos = savedPos0;
 1589+ }
 1590+ } else {
 1591+ var result1 = null;
 1592+ pos = savedPos0;
 1593+ }
 1594+ var result0 = result1 !== null
 1595+ ? (function() { return "*"; })()
 1596+ : null;
 1597+
 1598+
 1599+
 1600+ cache[cacheKey] = {
 1601+ nextPos: pos,
 1602+ result: result0
 1603+ };
 1604+ return result0;
 1605+ }
 1606+
 1607+ function parse_plus() {
 1608+ var cacheKey = 'plus@' + pos;
 1609+ var cachedResult = cache[cacheKey];
 1610+ if (cachedResult) {
 1611+ pos = cachedResult.nextPos;
 1612+ return cachedResult.result;
 1613+ }
 1614+
 1615+
 1616+ var savedPos0 = pos;
 1617+ if (input.substr(pos, 1) === "+") {
 1618+ var result2 = "+";
 1619+ pos += 1;
 1620+ } else {
 1621+ var result2 = null;
 1622+ if (reportMatchFailures) {
 1623+ matchFailed("\"+\"");
 1624+ }
 1625+ }
 1626+ if (result2 !== null) {
 1627+ var result3 = parse___();
 1628+ if (result3 !== null) {
 1629+ var result1 = [result2, result3];
 1630+ } else {
 1631+ var result1 = null;
 1632+ pos = savedPos0;
 1633+ }
 1634+ } else {
 1635+ var result1 = null;
 1636+ pos = savedPos0;
 1637+ }
 1638+ var result0 = result1 !== null
 1639+ ? (function() { return "+"; })()
 1640+ : null;
 1641+
 1642+
 1643+
 1644+ cache[cacheKey] = {
 1645+ nextPos: pos,
 1646+ result: result0
 1647+ };
 1648+ return result0;
 1649+ }
 1650+
 1651+ function parse_lparen() {
 1652+ var cacheKey = 'lparen@' + pos;
 1653+ var cachedResult = cache[cacheKey];
 1654+ if (cachedResult) {
 1655+ pos = cachedResult.nextPos;
 1656+ return cachedResult.result;
 1657+ }
 1658+
 1659+
 1660+ var savedPos0 = pos;
 1661+ if (input.substr(pos, 1) === "(") {
 1662+ var result2 = "(";
 1663+ pos += 1;
 1664+ } else {
 1665+ var result2 = null;
 1666+ if (reportMatchFailures) {
 1667+ matchFailed("\"(\"");
 1668+ }
 1669+ }
 1670+ if (result2 !== null) {
 1671+ var result3 = parse___();
 1672+ if (result3 !== null) {
 1673+ var result1 = [result2, result3];
 1674+ } else {
 1675+ var result1 = null;
 1676+ pos = savedPos0;
 1677+ }
 1678+ } else {
 1679+ var result1 = null;
 1680+ pos = savedPos0;
 1681+ }
 1682+ var result0 = result1 !== null
 1683+ ? (function() { return "("; })()
 1684+ : null;
 1685+
 1686+
 1687+
 1688+ cache[cacheKey] = {
 1689+ nextPos: pos,
 1690+ result: result0
 1691+ };
 1692+ return result0;
 1693+ }
 1694+
 1695+ function parse_rparen() {
 1696+ var cacheKey = 'rparen@' + pos;
 1697+ var cachedResult = cache[cacheKey];
 1698+ if (cachedResult) {
 1699+ pos = cachedResult.nextPos;
 1700+ return cachedResult.result;
 1701+ }
 1702+
 1703+
 1704+ var savedPos0 = pos;
 1705+ if (input.substr(pos, 1) === ")") {
 1706+ var result2 = ")";
 1707+ pos += 1;
 1708+ } else {
 1709+ var result2 = null;
 1710+ if (reportMatchFailures) {
 1711+ matchFailed("\")\"");
 1712+ }
 1713+ }
 1714+ if (result2 !== null) {
 1715+ var result3 = parse___();
 1716+ if (result3 !== null) {
 1717+ var result1 = [result2, result3];
 1718+ } else {
 1719+ var result1 = null;
 1720+ pos = savedPos0;
 1721+ }
 1722+ } else {
 1723+ var result1 = null;
 1724+ pos = savedPos0;
 1725+ }
 1726+ var result0 = result1 !== null
 1727+ ? (function() { return ")"; })()
 1728+ : null;
 1729+
 1730+
 1731+
 1732+ cache[cacheKey] = {
 1733+ nextPos: pos,
 1734+ result: result0
 1735+ };
 1736+ return result0;
 1737+ }
 1738+
 1739+ function parse_dot() {
 1740+ var cacheKey = 'dot@' + pos;
 1741+ var cachedResult = cache[cacheKey];
 1742+ if (cachedResult) {
 1743+ pos = cachedResult.nextPos;
 1744+ return cachedResult.result;
 1745+ }
 1746+
 1747+
 1748+ var savedPos0 = pos;
 1749+ if (input.substr(pos, 1) === ".") {
 1750+ var result2 = ".";
 1751+ pos += 1;
 1752+ } else {
 1753+ var result2 = null;
 1754+ if (reportMatchFailures) {
 1755+ matchFailed("\".\"");
 1756+ }
 1757+ }
 1758+ if (result2 !== null) {
 1759+ var result3 = parse___();
 1760+ if (result3 !== null) {
 1761+ var result1 = [result2, result3];
 1762+ } else {
 1763+ var result1 = null;
 1764+ pos = savedPos0;
 1765+ }
 1766+ } else {
 1767+ var result1 = null;
 1768+ pos = savedPos0;
 1769+ }
 1770+ var result0 = result1 !== null
 1771+ ? (function() { return "."; })()
 1772+ : null;
 1773+
 1774+
 1775+
 1776+ cache[cacheKey] = {
 1777+ nextPos: pos,
 1778+ result: result0
 1779+ };
 1780+ return result0;
 1781+ }
 1782+
 1783+ function parse_identifier() {
 1784+ var cacheKey = 'identifier@' + pos;
 1785+ var cachedResult = cache[cacheKey];
 1786+ if (cachedResult) {
 1787+ pos = cachedResult.nextPos;
 1788+ return cachedResult.result;
 1789+ }
 1790+
 1791+ var savedReportMatchFailures = reportMatchFailures;
 1792+ reportMatchFailures = false;
 1793+ var savedPos0 = pos;
 1794+ var result12 = parse_letter();
 1795+ if (result12 !== null) {
 1796+ var result2 = result12;
 1797+ } else {
 1798+ if (input.substr(pos, 1) === "_") {
 1799+ var result11 = "_";
 1800+ pos += 1;
 1801+ } else {
 1802+ var result11 = null;
 1803+ if (reportMatchFailures) {
 1804+ matchFailed("\"_\"");
 1805+ }
 1806+ }
 1807+ if (result11 !== null) {
 1808+ var result2 = result11;
 1809+ } else {
 1810+ if (input.substr(pos, 1) === "$") {
 1811+ var result10 = "$";
 1812+ pos += 1;
 1813+ } else {
 1814+ var result10 = null;
 1815+ if (reportMatchFailures) {
 1816+ matchFailed("\"$\"");
 1817+ }
 1818+ }
 1819+ if (result10 !== null) {
 1820+ var result2 = result10;
 1821+ } else {
 1822+ var result2 = null;;
 1823+ };
 1824+ };
 1825+ }
 1826+ if (result2 !== null) {
 1827+ var result3 = [];
 1828+ var result9 = parse_letter();
 1829+ if (result9 !== null) {
 1830+ var result5 = result9;
 1831+ } else {
 1832+ var result8 = parse_digit();
 1833+ if (result8 !== null) {
 1834+ var result5 = result8;
 1835+ } else {
 1836+ if (input.substr(pos, 1) === "_") {
 1837+ var result7 = "_";
 1838+ pos += 1;
 1839+ } else {
 1840+ var result7 = null;
 1841+ if (reportMatchFailures) {
 1842+ matchFailed("\"_\"");
 1843+ }
 1844+ }
 1845+ if (result7 !== null) {
 1846+ var result5 = result7;
 1847+ } else {
 1848+ if (input.substr(pos, 1) === "$") {
 1849+ var result6 = "$";
 1850+ pos += 1;
 1851+ } else {
 1852+ var result6 = null;
 1853+ if (reportMatchFailures) {
 1854+ matchFailed("\"$\"");
 1855+ }
 1856+ }
 1857+ if (result6 !== null) {
 1858+ var result5 = result6;
 1859+ } else {
 1860+ var result5 = null;;
 1861+ };
 1862+ };
 1863+ };
 1864+ }
 1865+ while (result5 !== null) {
 1866+ result3.push(result5);
 1867+ var result9 = parse_letter();
 1868+ if (result9 !== null) {
 1869+ var result5 = result9;
 1870+ } else {
 1871+ var result8 = parse_digit();
 1872+ if (result8 !== null) {
 1873+ var result5 = result8;
 1874+ } else {
 1875+ if (input.substr(pos, 1) === "_") {
 1876+ var result7 = "_";
 1877+ pos += 1;
 1878+ } else {
 1879+ var result7 = null;
 1880+ if (reportMatchFailures) {
 1881+ matchFailed("\"_\"");
 1882+ }
 1883+ }
 1884+ if (result7 !== null) {
 1885+ var result5 = result7;
 1886+ } else {
 1887+ if (input.substr(pos, 1) === "$") {
 1888+ var result6 = "$";
 1889+ pos += 1;
 1890+ } else {
 1891+ var result6 = null;
 1892+ if (reportMatchFailures) {
 1893+ matchFailed("\"$\"");
 1894+ }
 1895+ }
 1896+ if (result6 !== null) {
 1897+ var result5 = result6;
 1898+ } else {
 1899+ var result5 = null;;
 1900+ };
 1901+ };
 1902+ };
 1903+ }
 1904+ }
 1905+ if (result3 !== null) {
 1906+ var result4 = parse___();
 1907+ if (result4 !== null) {
 1908+ var result1 = [result2, result3, result4];
 1909+ } else {
 1910+ var result1 = null;
 1911+ pos = savedPos0;
 1912+ }
 1913+ } else {
 1914+ var result1 = null;
 1915+ pos = savedPos0;
 1916+ }
 1917+ } else {
 1918+ var result1 = null;
 1919+ pos = savedPos0;
 1920+ }
 1921+ var result0 = result1 !== null
 1922+ ? (function(head, tail) {
 1923+ return head + tail.join("");
 1924+ })(result1[0], result1[1])
 1925+ : null;
 1926+ reportMatchFailures = savedReportMatchFailures;
 1927+ if (reportMatchFailures && result0 === null) {
 1928+ matchFailed("identifier");
 1929+ }
 1930+
 1931+ cache[cacheKey] = {
 1932+ nextPos: pos,
 1933+ result: result0
 1934+ };
 1935+ return result0;
 1936+ }
 1937+
 1938+ function parse_literal() {
 1939+ var cacheKey = 'literal@' + pos;
 1940+ var cachedResult = cache[cacheKey];
 1941+ if (cachedResult) {
 1942+ pos = cachedResult.nextPos;
 1943+ return cachedResult.result;
 1944+ }
 1945+
 1946+ var savedReportMatchFailures = reportMatchFailures;
 1947+ reportMatchFailures = false;
 1948+ var savedPos0 = pos;
 1949+ var result5 = parse_doubleQuotedLiteral();
 1950+ if (result5 !== null) {
 1951+ var result2 = result5;
 1952+ } else {
 1953+ var result4 = parse_singleQuotedLiteral();
 1954+ if (result4 !== null) {
 1955+ var result2 = result4;
 1956+ } else {
 1957+ var result2 = null;;
 1958+ };
 1959+ }
 1960+ if (result2 !== null) {
 1961+ var result3 = parse___();
 1962+ if (result3 !== null) {
 1963+ var result1 = [result2, result3];
 1964+ } else {
 1965+ var result1 = null;
 1966+ pos = savedPos0;
 1967+ }
 1968+ } else {
 1969+ var result1 = null;
 1970+ pos = savedPos0;
 1971+ }
 1972+ var result0 = result1 !== null
 1973+ ? (function(literal) { return literal; })(result1[0])
 1974+ : null;
 1975+ reportMatchFailures = savedReportMatchFailures;
 1976+ if (reportMatchFailures && result0 === null) {
 1977+ matchFailed("literal");
 1978+ }
 1979+
 1980+ cache[cacheKey] = {
 1981+ nextPos: pos,
 1982+ result: result0
 1983+ };
 1984+ return result0;
 1985+ }
 1986+
 1987+ function parse_doubleQuotedLiteral() {
 1988+ var cacheKey = 'doubleQuotedLiteral@' + pos;
 1989+ var cachedResult = cache[cacheKey];
 1990+ if (cachedResult) {
 1991+ pos = cachedResult.nextPos;
 1992+ return cachedResult.result;
 1993+ }
 1994+
 1995+
 1996+ var savedPos0 = pos;
 1997+ if (input.substr(pos, 1) === "\"") {
 1998+ var result2 = "\"";
 1999+ pos += 1;
 2000+ } else {
 2001+ var result2 = null;
 2002+ if (reportMatchFailures) {
 2003+ matchFailed("\"\\\"\"");
 2004+ }
 2005+ }
 2006+ if (result2 !== null) {
 2007+ var result3 = [];
 2008+ var result5 = parse_doubleQuotedCharacter();
 2009+ while (result5 !== null) {
 2010+ result3.push(result5);
 2011+ var result5 = parse_doubleQuotedCharacter();
 2012+ }
 2013+ if (result3 !== null) {
 2014+ if (input.substr(pos, 1) === "\"") {
 2015+ var result4 = "\"";
 2016+ pos += 1;
 2017+ } else {
 2018+ var result4 = null;
 2019+ if (reportMatchFailures) {
 2020+ matchFailed("\"\\\"\"");
 2021+ }
 2022+ }
 2023+ if (result4 !== null) {
 2024+ var result1 = [result2, result3, result4];
 2025+ } else {
 2026+ var result1 = null;
 2027+ pos = savedPos0;
 2028+ }
 2029+ } else {
 2030+ var result1 = null;
 2031+ pos = savedPos0;
 2032+ }
 2033+ } else {
 2034+ var result1 = null;
 2035+ pos = savedPos0;
 2036+ }
 2037+ var result0 = result1 !== null
 2038+ ? (function(chars) { return chars.join(""); })(result1[1])
 2039+ : null;
 2040+
 2041+
 2042+
 2043+ cache[cacheKey] = {
 2044+ nextPos: pos,
 2045+ result: result0
 2046+ };
 2047+ return result0;
 2048+ }
 2049+
 2050+ function parse_doubleQuotedCharacter() {
 2051+ var cacheKey = 'doubleQuotedCharacter@' + pos;
 2052+ var cachedResult = cache[cacheKey];
 2053+ if (cachedResult) {
 2054+ pos = cachedResult.nextPos;
 2055+ return cachedResult.result;
 2056+ }
 2057+
 2058+
 2059+ var result6 = parse_simpleDoubleQuotedCharacter();
 2060+ if (result6 !== null) {
 2061+ var result0 = result6;
 2062+ } else {
 2063+ var result5 = parse_simpleEscapeSequence();
 2064+ if (result5 !== null) {
 2065+ var result0 = result5;
 2066+ } else {
 2067+ var result4 = parse_zeroEscapeSequence();
 2068+ if (result4 !== null) {
 2069+ var result0 = result4;
 2070+ } else {
 2071+ var result3 = parse_hexEscapeSequence();
 2072+ if (result3 !== null) {
 2073+ var result0 = result3;
 2074+ } else {
 2075+ var result2 = parse_unicodeEscapeSequence();
 2076+ if (result2 !== null) {
 2077+ var result0 = result2;
 2078+ } else {
 2079+ var result1 = parse_eolEscapeSequence();
 2080+ if (result1 !== null) {
 2081+ var result0 = result1;
 2082+ } else {
 2083+ var result0 = null;;
 2084+ };
 2085+ };
 2086+ };
 2087+ };
 2088+ };
 2089+ }
 2090+
 2091+
 2092+
 2093+ cache[cacheKey] = {
 2094+ nextPos: pos,
 2095+ result: result0
 2096+ };
 2097+ return result0;
 2098+ }
 2099+
 2100+ function parse_simpleDoubleQuotedCharacter() {
 2101+ var cacheKey = 'simpleDoubleQuotedCharacter@' + pos;
 2102+ var cachedResult = cache[cacheKey];
 2103+ if (cachedResult) {
 2104+ pos = cachedResult.nextPos;
 2105+ return cachedResult.result;
 2106+ }
 2107+
 2108+
 2109+ var savedPos0 = pos;
 2110+ var savedPos1 = pos;
 2111+ var savedReportMatchFailuresVar0 = reportMatchFailures;
 2112+ reportMatchFailures = false;
 2113+ if (input.substr(pos, 1) === "\"") {
 2114+ var result7 = "\"";
 2115+ pos += 1;
 2116+ } else {
 2117+ var result7 = null;
 2118+ if (reportMatchFailures) {
 2119+ matchFailed("\"\\\"\"");
 2120+ }
 2121+ }
 2122+ if (result7 !== null) {
 2123+ var result4 = result7;
 2124+ } else {
 2125+ if (input.substr(pos, 1) === "\\") {
 2126+ var result6 = "\\";
 2127+ pos += 1;
 2128+ } else {
 2129+ var result6 = null;
 2130+ if (reportMatchFailures) {
 2131+ matchFailed("\"\\\\\"");
 2132+ }
 2133+ }
 2134+ if (result6 !== null) {
 2135+ var result4 = result6;
 2136+ } else {
 2137+ var result5 = parse_eolChar();
 2138+ if (result5 !== null) {
 2139+ var result4 = result5;
 2140+ } else {
 2141+ var result4 = null;;
 2142+ };
 2143+ };
 2144+ }
 2145+ reportMatchFailures = savedReportMatchFailuresVar0;
 2146+ if (result4 === null) {
 2147+ var result2 = '';
 2148+ } else {
 2149+ var result2 = null;
 2150+ pos = savedPos1;
 2151+ }
 2152+ if (result2 !== null) {
 2153+ if (input.length > pos) {
 2154+ var result3 = input.charAt(pos);
 2155+ pos++;
 2156+ } else {
 2157+ var result3 = null;
 2158+ if (reportMatchFailures) {
 2159+ matchFailed('any character');
 2160+ }
 2161+ }
 2162+ if (result3 !== null) {
 2163+ var result1 = [result2, result3];
 2164+ } else {
 2165+ var result1 = null;
 2166+ pos = savedPos0;
 2167+ }
 2168+ } else {
 2169+ var result1 = null;
 2170+ pos = savedPos0;
 2171+ }
 2172+ var result0 = result1 !== null
 2173+ ? (function(char_) { return char_; })(result1[1])
 2174+ : null;
 2175+
 2176+
 2177+
 2178+ cache[cacheKey] = {
 2179+ nextPos: pos,
 2180+ result: result0
 2181+ };
 2182+ return result0;
 2183+ }
 2184+
 2185+ function parse_singleQuotedLiteral() {
 2186+ var cacheKey = 'singleQuotedLiteral@' + pos;
 2187+ var cachedResult = cache[cacheKey];
 2188+ if (cachedResult) {
 2189+ pos = cachedResult.nextPos;
 2190+ return cachedResult.result;
 2191+ }
 2192+
 2193+
 2194+ var savedPos0 = pos;
 2195+ if (input.substr(pos, 1) === "'") {
 2196+ var result2 = "'";
 2197+ pos += 1;
 2198+ } else {
 2199+ var result2 = null;
 2200+ if (reportMatchFailures) {
 2201+ matchFailed("\"'\"");
 2202+ }
 2203+ }
 2204+ if (result2 !== null) {
 2205+ var result3 = [];
 2206+ var result5 = parse_singleQuotedCharacter();
 2207+ while (result5 !== null) {
 2208+ result3.push(result5);
 2209+ var result5 = parse_singleQuotedCharacter();
 2210+ }
 2211+ if (result3 !== null) {
 2212+ if (input.substr(pos, 1) === "'") {
 2213+ var result4 = "'";
 2214+ pos += 1;
 2215+ } else {
 2216+ var result4 = null;
 2217+ if (reportMatchFailures) {
 2218+ matchFailed("\"'\"");
 2219+ }
 2220+ }
 2221+ if (result4 !== null) {
 2222+ var result1 = [result2, result3, result4];
 2223+ } else {
 2224+ var result1 = null;
 2225+ pos = savedPos0;
 2226+ }
 2227+ } else {
 2228+ var result1 = null;
 2229+ pos = savedPos0;
 2230+ }
 2231+ } else {
 2232+ var result1 = null;
 2233+ pos = savedPos0;
 2234+ }
 2235+ var result0 = result1 !== null
 2236+ ? (function(chars) { return chars.join(""); })(result1[1])
 2237+ : null;
 2238+
 2239+
 2240+
 2241+ cache[cacheKey] = {
 2242+ nextPos: pos,
 2243+ result: result0
 2244+ };
 2245+ return result0;
 2246+ }
 2247+
 2248+ function parse_singleQuotedCharacter() {
 2249+ var cacheKey = 'singleQuotedCharacter@' + pos;
 2250+ var cachedResult = cache[cacheKey];
 2251+ if (cachedResult) {
 2252+ pos = cachedResult.nextPos;
 2253+ return cachedResult.result;
 2254+ }
 2255+
 2256+
 2257+ var result6 = parse_simpleSingleQuotedCharacter();
 2258+ if (result6 !== null) {
 2259+ var result0 = result6;
 2260+ } else {
 2261+ var result5 = parse_simpleEscapeSequence();
 2262+ if (result5 !== null) {
 2263+ var result0 = result5;
 2264+ } else {
 2265+ var result4 = parse_zeroEscapeSequence();
 2266+ if (result4 !== null) {
 2267+ var result0 = result4;
 2268+ } else {
 2269+ var result3 = parse_hexEscapeSequence();
 2270+ if (result3 !== null) {
 2271+ var result0 = result3;
 2272+ } else {
 2273+ var result2 = parse_unicodeEscapeSequence();
 2274+ if (result2 !== null) {
 2275+ var result0 = result2;
 2276+ } else {
 2277+ var result1 = parse_eolEscapeSequence();
 2278+ if (result1 !== null) {
 2279+ var result0 = result1;
 2280+ } else {
 2281+ var result0 = null;;
 2282+ };
 2283+ };
 2284+ };
 2285+ };
 2286+ };
 2287+ }
 2288+
 2289+
 2290+
 2291+ cache[cacheKey] = {
 2292+ nextPos: pos,
 2293+ result: result0
 2294+ };
 2295+ return result0;
 2296+ }
 2297+
 2298+ function parse_simpleSingleQuotedCharacter() {
 2299+ var cacheKey = 'simpleSingleQuotedCharacter@' + pos;
 2300+ var cachedResult = cache[cacheKey];
 2301+ if (cachedResult) {
 2302+ pos = cachedResult.nextPos;
 2303+ return cachedResult.result;
 2304+ }
 2305+
 2306+
 2307+ var savedPos0 = pos;
 2308+ var savedPos1 = pos;
 2309+ var savedReportMatchFailuresVar0 = reportMatchFailures;
 2310+ reportMatchFailures = false;
 2311+ if (input.substr(pos, 1) === "'") {
 2312+ var result7 = "'";
 2313+ pos += 1;
 2314+ } else {
 2315+ var result7 = null;
 2316+ if (reportMatchFailures) {
 2317+ matchFailed("\"'\"");
 2318+ }
 2319+ }
 2320+ if (result7 !== null) {
 2321+ var result4 = result7;
 2322+ } else {
 2323+ if (input.substr(pos, 1) === "\\") {
 2324+ var result6 = "\\";
 2325+ pos += 1;
 2326+ } else {
 2327+ var result6 = null;
 2328+ if (reportMatchFailures) {
 2329+ matchFailed("\"\\\\\"");
 2330+ }
 2331+ }
 2332+ if (result6 !== null) {
 2333+ var result4 = result6;
 2334+ } else {
 2335+ var result5 = parse_eolChar();
 2336+ if (result5 !== null) {
 2337+ var result4 = result5;
 2338+ } else {
 2339+ var result4 = null;;
 2340+ };
 2341+ };
 2342+ }
 2343+ reportMatchFailures = savedReportMatchFailuresVar0;
 2344+ if (result4 === null) {
 2345+ var result2 = '';
 2346+ } else {
 2347+ var result2 = null;
 2348+ pos = savedPos1;
 2349+ }
 2350+ if (result2 !== null) {
 2351+ if (input.length > pos) {
 2352+ var result3 = input.charAt(pos);
 2353+ pos++;
 2354+ } else {
 2355+ var result3 = null;
 2356+ if (reportMatchFailures) {
 2357+ matchFailed('any character');
 2358+ }
 2359+ }
 2360+ if (result3 !== null) {
 2361+ var result1 = [result2, result3];
 2362+ } else {
 2363+ var result1 = null;
 2364+ pos = savedPos0;
 2365+ }
 2366+ } else {
 2367+ var result1 = null;
 2368+ pos = savedPos0;
 2369+ }
 2370+ var result0 = result1 !== null
 2371+ ? (function(char_) { return char_; })(result1[1])
 2372+ : null;
 2373+
 2374+
 2375+
 2376+ cache[cacheKey] = {
 2377+ nextPos: pos,
 2378+ result: result0
 2379+ };
 2380+ return result0;
 2381+ }
 2382+
 2383+ function parse_class() {
 2384+ var cacheKey = 'class@' + pos;
 2385+ var cachedResult = cache[cacheKey];
 2386+ if (cachedResult) {
 2387+ pos = cachedResult.nextPos;
 2388+ return cachedResult.result;
 2389+ }
 2390+
 2391+ var savedReportMatchFailures = reportMatchFailures;
 2392+ reportMatchFailures = false;
 2393+ var savedPos0 = pos;
 2394+ if (input.substr(pos, 1) === "[") {
 2395+ var result2 = "[";
 2396+ pos += 1;
 2397+ } else {
 2398+ var result2 = null;
 2399+ if (reportMatchFailures) {
 2400+ matchFailed("\"[\"");
 2401+ }
 2402+ }
 2403+ if (result2 !== null) {
 2404+ if (input.substr(pos, 1) === "^") {
 2405+ var result10 = "^";
 2406+ pos += 1;
 2407+ } else {
 2408+ var result10 = null;
 2409+ if (reportMatchFailures) {
 2410+ matchFailed("\"^\"");
 2411+ }
 2412+ }
 2413+ var result3 = result10 !== null ? result10 : '';
 2414+ if (result3 !== null) {
 2415+ var result4 = [];
 2416+ var result9 = parse_classCharacterRange();
 2417+ if (result9 !== null) {
 2418+ var result7 = result9;
 2419+ } else {
 2420+ var result8 = parse_classCharacter();
 2421+ if (result8 !== null) {
 2422+ var result7 = result8;
 2423+ } else {
 2424+ var result7 = null;;
 2425+ };
 2426+ }
 2427+ while (result7 !== null) {
 2428+ result4.push(result7);
 2429+ var result9 = parse_classCharacterRange();
 2430+ if (result9 !== null) {
 2431+ var result7 = result9;
 2432+ } else {
 2433+ var result8 = parse_classCharacter();
 2434+ if (result8 !== null) {
 2435+ var result7 = result8;
 2436+ } else {
 2437+ var result7 = null;;
 2438+ };
 2439+ }
 2440+ }
 2441+ if (result4 !== null) {
 2442+ if (input.substr(pos, 1) === "]") {
 2443+ var result5 = "]";
 2444+ pos += 1;
 2445+ } else {
 2446+ var result5 = null;
 2447+ if (reportMatchFailures) {
 2448+ matchFailed("\"]\"");
 2449+ }
 2450+ }
 2451+ if (result5 !== null) {
 2452+ var result6 = parse___();
 2453+ if (result6 !== null) {
 2454+ var result1 = [result2, result3, result4, result5, result6];
 2455+ } else {
 2456+ var result1 = null;
 2457+ pos = savedPos0;
 2458+ }
 2459+ } else {
 2460+ var result1 = null;
 2461+ pos = savedPos0;
 2462+ }
 2463+ } else {
 2464+ var result1 = null;
 2465+ pos = savedPos0;
 2466+ }
 2467+ } else {
 2468+ var result1 = null;
 2469+ pos = savedPos0;
 2470+ }
 2471+ } else {
 2472+ var result1 = null;
 2473+ pos = savedPos0;
 2474+ }
 2475+ var result0 = result1 !== null
 2476+ ? (function(inverted, parts) {
 2477+ var partsConverted = map(parts, function(part) { return part.data; });
 2478+ var rawText = "["
 2479+ + inverted
 2480+ + map(parts, function(part) { return part.rawText; }).join("")
 2481+ + "]";
 2482+
 2483+ return {
 2484+ type: "class",
 2485+ inverted: inverted === "^",
 2486+ parts: partsConverted,
 2487+ // FIXME: Get the raw text from the input directly.
 2488+ rawText: rawText
 2489+ };
 2490+ })(result1[1], result1[2])
 2491+ : null;
 2492+ reportMatchFailures = savedReportMatchFailures;
 2493+ if (reportMatchFailures && result0 === null) {
 2494+ matchFailed("character class");
 2495+ }
 2496+
 2497+ cache[cacheKey] = {
 2498+ nextPos: pos,
 2499+ result: result0
 2500+ };
 2501+ return result0;
 2502+ }
 2503+
 2504+ function parse_classCharacterRange() {
 2505+ var cacheKey = 'classCharacterRange@' + pos;
 2506+ var cachedResult = cache[cacheKey];
 2507+ if (cachedResult) {
 2508+ pos = cachedResult.nextPos;
 2509+ return cachedResult.result;
 2510+ }
 2511+
 2512+
 2513+ var savedPos0 = pos;
 2514+ var result2 = parse_classCharacter();
 2515+ if (result2 !== null) {
 2516+ if (input.substr(pos, 1) === "-") {
 2517+ var result3 = "-";
 2518+ pos += 1;
 2519+ } else {
 2520+ var result3 = null;
 2521+ if (reportMatchFailures) {
 2522+ matchFailed("\"-\"");
 2523+ }
 2524+ }
 2525+ if (result3 !== null) {
 2526+ var result4 = parse_classCharacter();
 2527+ if (result4 !== null) {
 2528+ var result1 = [result2, result3, result4];
 2529+ } else {
 2530+ var result1 = null;
 2531+ pos = savedPos0;
 2532+ }
 2533+ } else {
 2534+ var result1 = null;
 2535+ pos = savedPos0;
 2536+ }
 2537+ } else {
 2538+ var result1 = null;
 2539+ pos = savedPos0;
 2540+ }
 2541+ var result0 = result1 !== null
 2542+ ? (function(begin, end) {
 2543+ if (begin.data.charCodeAt(0) > end.data.charCodeAt(0)) {
 2544+ throw new this.SyntaxError(
 2545+ "Invalid character range: " + begin.rawText + "-" + end.rawText + "."
 2546+ );
 2547+ }
 2548+
 2549+ return {
 2550+ data: [begin.data, end.data],
 2551+ // FIXME: Get the raw text from the input directly.
 2552+ rawText: begin.rawText + "-" + end.rawText
 2553+ }
 2554+ })(result1[0], result1[2])
 2555+ : null;
 2556+
 2557+
 2558+
 2559+ cache[cacheKey] = {
 2560+ nextPos: pos,
 2561+ result: result0
 2562+ };
 2563+ return result0;
 2564+ }
 2565+
 2566+ function parse_classCharacter() {
 2567+ var cacheKey = 'classCharacter@' + pos;
 2568+ var cachedResult = cache[cacheKey];
 2569+ if (cachedResult) {
 2570+ pos = cachedResult.nextPos;
 2571+ return cachedResult.result;
 2572+ }
 2573+
 2574+
 2575+ var result1 = parse_bracketDelimitedCharacter();
 2576+ var result0 = result1 !== null
 2577+ ? (function(char_) {
 2578+ return {
 2579+ data: char_,
 2580+ // FIXME: Get the raw text from the input directly.
 2581+ rawText: quoteForRegexpClass(char_)
 2582+ };
 2583+ })(result1)
 2584+ : null;
 2585+
 2586+
 2587+
 2588+ cache[cacheKey] = {
 2589+ nextPos: pos,
 2590+ result: result0
 2591+ };
 2592+ return result0;
 2593+ }
 2594+
 2595+ function parse_bracketDelimitedCharacter() {
 2596+ var cacheKey = 'bracketDelimitedCharacter@' + pos;
 2597+ var cachedResult = cache[cacheKey];
 2598+ if (cachedResult) {
 2599+ pos = cachedResult.nextPos;
 2600+ return cachedResult.result;
 2601+ }
 2602+
 2603+
 2604+ var result6 = parse_simpleBracketDelimitedCharacter();
 2605+ if (result6 !== null) {
 2606+ var result0 = result6;
 2607+ } else {
 2608+ var result5 = parse_simpleEscapeSequence();
 2609+ if (result5 !== null) {
 2610+ var result0 = result5;
 2611+ } else {
 2612+ var result4 = parse_zeroEscapeSequence();
 2613+ if (result4 !== null) {
 2614+ var result0 = result4;
 2615+ } else {
 2616+ var result3 = parse_hexEscapeSequence();
 2617+ if (result3 !== null) {
 2618+ var result0 = result3;
 2619+ } else {
 2620+ var result2 = parse_unicodeEscapeSequence();
 2621+ if (result2 !== null) {
 2622+ var result0 = result2;
 2623+ } else {
 2624+ var result1 = parse_eolEscapeSequence();
 2625+ if (result1 !== null) {
 2626+ var result0 = result1;
 2627+ } else {
 2628+ var result0 = null;;
 2629+ };
 2630+ };
 2631+ };
 2632+ };
 2633+ };
 2634+ }
 2635+
 2636+
 2637+
 2638+ cache[cacheKey] = {
 2639+ nextPos: pos,
 2640+ result: result0
 2641+ };
 2642+ return result0;
 2643+ }
 2644+
 2645+ function parse_simpleBracketDelimitedCharacter() {
 2646+ var cacheKey = 'simpleBracketDelimitedCharacter@' + pos;
 2647+ var cachedResult = cache[cacheKey];
 2648+ if (cachedResult) {
 2649+ pos = cachedResult.nextPos;
 2650+ return cachedResult.result;
 2651+ }
 2652+
 2653+
 2654+ var savedPos0 = pos;
 2655+ var savedPos1 = pos;
 2656+ var savedReportMatchFailuresVar0 = reportMatchFailures;
 2657+ reportMatchFailures = false;
 2658+ if (input.substr(pos, 1) === "]") {
 2659+ var result7 = "]";
 2660+ pos += 1;
 2661+ } else {
 2662+ var result7 = null;
 2663+ if (reportMatchFailures) {
 2664+ matchFailed("\"]\"");
 2665+ }
 2666+ }
 2667+ if (result7 !== null) {
 2668+ var result4 = result7;
 2669+ } else {
 2670+ if (input.substr(pos, 1) === "\\") {
 2671+ var result6 = "\\";
 2672+ pos += 1;
 2673+ } else {
 2674+ var result6 = null;
 2675+ if (reportMatchFailures) {
 2676+ matchFailed("\"\\\\\"");
 2677+ }
 2678+ }
 2679+ if (result6 !== null) {
 2680+ var result4 = result6;
 2681+ } else {
 2682+ var result5 = parse_eolChar();
 2683+ if (result5 !== null) {
 2684+ var result4 = result5;
 2685+ } else {
 2686+ var result4 = null;;
 2687+ };
 2688+ };
 2689+ }
 2690+ reportMatchFailures = savedReportMatchFailuresVar0;
 2691+ if (result4 === null) {
 2692+ var result2 = '';
 2693+ } else {
 2694+ var result2 = null;
 2695+ pos = savedPos1;
 2696+ }
 2697+ if (result2 !== null) {
 2698+ if (input.length > pos) {
 2699+ var result3 = input.charAt(pos);
 2700+ pos++;
 2701+ } else {
 2702+ var result3 = null;
 2703+ if (reportMatchFailures) {
 2704+ matchFailed('any character');
 2705+ }
 2706+ }
 2707+ if (result3 !== null) {
 2708+ var result1 = [result2, result3];
 2709+ } else {
 2710+ var result1 = null;
 2711+ pos = savedPos0;
 2712+ }
 2713+ } else {
 2714+ var result1 = null;
 2715+ pos = savedPos0;
 2716+ }
 2717+ var result0 = result1 !== null
 2718+ ? (function(char_) { return char_; })(result1[1])
 2719+ : null;
 2720+
 2721+
 2722+
 2723+ cache[cacheKey] = {
 2724+ nextPos: pos,
 2725+ result: result0
 2726+ };
 2727+ return result0;
 2728+ }
 2729+
 2730+ function parse_simpleEscapeSequence() {
 2731+ var cacheKey = 'simpleEscapeSequence@' + pos;
 2732+ var cachedResult = cache[cacheKey];
 2733+ if (cachedResult) {
 2734+ pos = cachedResult.nextPos;
 2735+ return cachedResult.result;
 2736+ }
 2737+
 2738+
 2739+ var savedPos0 = pos;
 2740+ if (input.substr(pos, 1) === "\\") {
 2741+ var result2 = "\\";
 2742+ pos += 1;
 2743+ } else {
 2744+ var result2 = null;
 2745+ if (reportMatchFailures) {
 2746+ matchFailed("\"\\\\\"");
 2747+ }
 2748+ }
 2749+ if (result2 !== null) {
 2750+ var savedPos1 = pos;
 2751+ var savedReportMatchFailuresVar0 = reportMatchFailures;
 2752+ reportMatchFailures = false;
 2753+ var result9 = parse_digit();
 2754+ if (result9 !== null) {
 2755+ var result5 = result9;
 2756+ } else {
 2757+ if (input.substr(pos, 1) === "x") {
 2758+ var result8 = "x";
 2759+ pos += 1;
 2760+ } else {
 2761+ var result8 = null;
 2762+ if (reportMatchFailures) {
 2763+ matchFailed("\"x\"");
 2764+ }
 2765+ }
 2766+ if (result8 !== null) {
 2767+ var result5 = result8;
 2768+ } else {
 2769+ if (input.substr(pos, 1) === "u") {
 2770+ var result7 = "u";
 2771+ pos += 1;
 2772+ } else {
 2773+ var result7 = null;
 2774+ if (reportMatchFailures) {
 2775+ matchFailed("\"u\"");
 2776+ }
 2777+ }
 2778+ if (result7 !== null) {
 2779+ var result5 = result7;
 2780+ } else {
 2781+ var result6 = parse_eolChar();
 2782+ if (result6 !== null) {
 2783+ var result5 = result6;
 2784+ } else {
 2785+ var result5 = null;;
 2786+ };
 2787+ };
 2788+ };
 2789+ }
 2790+ reportMatchFailures = savedReportMatchFailuresVar0;
 2791+ if (result5 === null) {
 2792+ var result3 = '';
 2793+ } else {
 2794+ var result3 = null;
 2795+ pos = savedPos1;
 2796+ }
 2797+ if (result3 !== null) {
 2798+ if (input.length > pos) {
 2799+ var result4 = input.charAt(pos);
 2800+ pos++;
 2801+ } else {
 2802+ var result4 = null;
 2803+ if (reportMatchFailures) {
 2804+ matchFailed('any character');
 2805+ }
 2806+ }
 2807+ if (result4 !== null) {
 2808+ var result1 = [result2, result3, result4];
 2809+ } else {
 2810+ var result1 = null;
 2811+ pos = savedPos0;
 2812+ }
 2813+ } else {
 2814+ var result1 = null;
 2815+ pos = savedPos0;
 2816+ }
 2817+ } else {
 2818+ var result1 = null;
 2819+ pos = savedPos0;
 2820+ }
 2821+ var result0 = result1 !== null
 2822+ ? (function(char_) {
 2823+ return char_
 2824+ .replace("b", "\b")
 2825+ .replace("f", "\f")
 2826+ .replace("n", "\n")
 2827+ .replace("r", "\r")
 2828+ .replace("t", "\t")
 2829+ .replace("v", "\x0B") // IE does not recognize "\v".
 2830+ })(result1[2])
 2831+ : null;
 2832+
 2833+
 2834+
 2835+ cache[cacheKey] = {
 2836+ nextPos: pos,
 2837+ result: result0
 2838+ };
 2839+ return result0;
 2840+ }
 2841+
 2842+ function parse_zeroEscapeSequence() {
 2843+ var cacheKey = 'zeroEscapeSequence@' + pos;
 2844+ var cachedResult = cache[cacheKey];
 2845+ if (cachedResult) {
 2846+ pos = cachedResult.nextPos;
 2847+ return cachedResult.result;
 2848+ }
 2849+
 2850+
 2851+ var savedPos0 = pos;
 2852+ if (input.substr(pos, 2) === "\\0") {
 2853+ var result2 = "\\0";
 2854+ pos += 2;
 2855+ } else {
 2856+ var result2 = null;
 2857+ if (reportMatchFailures) {
 2858+ matchFailed("\"\\\\0\"");
 2859+ }
 2860+ }
 2861+ if (result2 !== null) {
 2862+ var savedPos1 = pos;
 2863+ var savedReportMatchFailuresVar0 = reportMatchFailures;
 2864+ reportMatchFailures = false;
 2865+ var result4 = parse_digit();
 2866+ reportMatchFailures = savedReportMatchFailuresVar0;
 2867+ if (result4 === null) {
 2868+ var result3 = '';
 2869+ } else {
 2870+ var result3 = null;
 2871+ pos = savedPos1;
 2872+ }
 2873+ if (result3 !== null) {
 2874+ var result1 = [result2, result3];
 2875+ } else {
 2876+ var result1 = null;
 2877+ pos = savedPos0;
 2878+ }
 2879+ } else {
 2880+ var result1 = null;
 2881+ pos = savedPos0;
 2882+ }
 2883+ var result0 = result1 !== null
 2884+ ? (function() { return "\0"; })()
 2885+ : null;
 2886+
 2887+
 2888+
 2889+ cache[cacheKey] = {
 2890+ nextPos: pos,
 2891+ result: result0
 2892+ };
 2893+ return result0;
 2894+ }
 2895+
 2896+ function parse_hexEscapeSequence() {
 2897+ var cacheKey = 'hexEscapeSequence@' + pos;
 2898+ var cachedResult = cache[cacheKey];
 2899+ if (cachedResult) {
 2900+ pos = cachedResult.nextPos;
 2901+ return cachedResult.result;
 2902+ }
 2903+
 2904+
 2905+ var savedPos0 = pos;
 2906+ if (input.substr(pos, 2) === "\\x") {
 2907+ var result2 = "\\x";
 2908+ pos += 2;
 2909+ } else {
 2910+ var result2 = null;
 2911+ if (reportMatchFailures) {
 2912+ matchFailed("\"\\\\x\"");
 2913+ }
 2914+ }
 2915+ if (result2 !== null) {
 2916+ var result3 = parse_hexDigit();
 2917+ if (result3 !== null) {
 2918+ var result4 = parse_hexDigit();
 2919+ if (result4 !== null) {
 2920+ var result1 = [result2, result3, result4];
 2921+ } else {
 2922+ var result1 = null;
 2923+ pos = savedPos0;
 2924+ }
 2925+ } else {
 2926+ var result1 = null;
 2927+ pos = savedPos0;
 2928+ }
 2929+ } else {
 2930+ var result1 = null;
 2931+ pos = savedPos0;
 2932+ }
 2933+ var result0 = result1 !== null
 2934+ ? (function(h1, h2) {
 2935+ return String.fromCharCode(parseInt("0x" + h1 + h2));
 2936+ })(result1[1], result1[2])
 2937+ : null;
 2938+
 2939+
 2940+
 2941+ cache[cacheKey] = {
 2942+ nextPos: pos,
 2943+ result: result0
 2944+ };
 2945+ return result0;
 2946+ }
 2947+
 2948+ function parse_unicodeEscapeSequence() {
 2949+ var cacheKey = 'unicodeEscapeSequence@' + pos;
 2950+ var cachedResult = cache[cacheKey];
 2951+ if (cachedResult) {
 2952+ pos = cachedResult.nextPos;
 2953+ return cachedResult.result;
 2954+ }
 2955+
 2956+
 2957+ var savedPos0 = pos;
 2958+ if (input.substr(pos, 2) === "\\u") {
 2959+ var result2 = "\\u";
 2960+ pos += 2;
 2961+ } else {
 2962+ var result2 = null;
 2963+ if (reportMatchFailures) {
 2964+ matchFailed("\"\\\\u\"");
 2965+ }
 2966+ }
 2967+ if (result2 !== null) {
 2968+ var result3 = parse_hexDigit();
 2969+ if (result3 !== null) {
 2970+ var result4 = parse_hexDigit();
 2971+ if (result4 !== null) {
 2972+ var result5 = parse_hexDigit();
 2973+ if (result5 !== null) {
 2974+ var result6 = parse_hexDigit();
 2975+ if (result6 !== null) {
 2976+ var result1 = [result2, result3, result4, result5, result6];
 2977+ } else {
 2978+ var result1 = null;
 2979+ pos = savedPos0;
 2980+ }
 2981+ } else {
 2982+ var result1 = null;
 2983+ pos = savedPos0;
 2984+ }
 2985+ } else {
 2986+ var result1 = null;
 2987+ pos = savedPos0;
 2988+ }
 2989+ } else {
 2990+ var result1 = null;
 2991+ pos = savedPos0;
 2992+ }
 2993+ } else {
 2994+ var result1 = null;
 2995+ pos = savedPos0;
 2996+ }
 2997+ var result0 = result1 !== null
 2998+ ? (function(h1, h2, h3, h4) {
 2999+ return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4));
 3000+ })(result1[1], result1[2], result1[3], result1[4])
 3001+ : null;
 3002+
 3003+
 3004+
 3005+ cache[cacheKey] = {
 3006+ nextPos: pos,
 3007+ result: result0
 3008+ };
 3009+ return result0;
 3010+ }
 3011+
 3012+ function parse_eolEscapeSequence() {
 3013+ var cacheKey = 'eolEscapeSequence@' + pos;
 3014+ var cachedResult = cache[cacheKey];
 3015+ if (cachedResult) {
 3016+ pos = cachedResult.nextPos;
 3017+ return cachedResult.result;
 3018+ }
 3019+
 3020+
 3021+ var savedPos0 = pos;
 3022+ if (input.substr(pos, 1) === "\\") {
 3023+ var result2 = "\\";
 3024+ pos += 1;
 3025+ } else {
 3026+ var result2 = null;
 3027+ if (reportMatchFailures) {
 3028+ matchFailed("\"\\\\\"");
 3029+ }
 3030+ }
 3031+ if (result2 !== null) {
 3032+ var result3 = parse_eol();
 3033+ if (result3 !== null) {
 3034+ var result1 = [result2, result3];
 3035+ } else {
 3036+ var result1 = null;
 3037+ pos = savedPos0;
 3038+ }
 3039+ } else {
 3040+ var result1 = null;
 3041+ pos = savedPos0;
 3042+ }
 3043+ var result0 = result1 !== null
 3044+ ? (function(eol) { return eol; })(result1[1])
 3045+ : null;
 3046+
 3047+
 3048+
 3049+ cache[cacheKey] = {
 3050+ nextPos: pos,
 3051+ result: result0
 3052+ };
 3053+ return result0;
 3054+ }
 3055+
 3056+ function parse_digit() {
 3057+ var cacheKey = 'digit@' + pos;
 3058+ var cachedResult = cache[cacheKey];
 3059+ if (cachedResult) {
 3060+ pos = cachedResult.nextPos;
 3061+ return cachedResult.result;
 3062+ }
 3063+
 3064+
 3065+ if (input.substr(pos).match(/^[0-9]/) !== null) {
 3066+ var result0 = input.charAt(pos);
 3067+ pos++;
 3068+ } else {
 3069+ var result0 = null;
 3070+ if (reportMatchFailures) {
 3071+ matchFailed("[0-9]");
 3072+ }
 3073+ }
 3074+
 3075+
 3076+
 3077+ cache[cacheKey] = {
 3078+ nextPos: pos,
 3079+ result: result0
 3080+ };
 3081+ return result0;
 3082+ }
 3083+
 3084+ function parse_hexDigit() {
 3085+ var cacheKey = 'hexDigit@' + pos;
 3086+ var cachedResult = cache[cacheKey];
 3087+ if (cachedResult) {
 3088+ pos = cachedResult.nextPos;
 3089+ return cachedResult.result;
 3090+ }
 3091+
 3092+
 3093+ if (input.substr(pos).match(/^[0-9a-fA-F]/) !== null) {
 3094+ var result0 = input.charAt(pos);
 3095+ pos++;
 3096+ } else {
 3097+ var result0 = null;
 3098+ if (reportMatchFailures) {
 3099+ matchFailed("[0-9a-fA-F]");
 3100+ }
 3101+ }
 3102+
 3103+
 3104+
 3105+ cache[cacheKey] = {
 3106+ nextPos: pos,
 3107+ result: result0
 3108+ };
 3109+ return result0;
 3110+ }
 3111+
 3112+ function parse_letter() {
 3113+ var cacheKey = 'letter@' + pos;
 3114+ var cachedResult = cache[cacheKey];
 3115+ if (cachedResult) {
 3116+ pos = cachedResult.nextPos;
 3117+ return cachedResult.result;
 3118+ }
 3119+
 3120+
 3121+ var result2 = parse_lowerCaseLetter();
 3122+ if (result2 !== null) {
 3123+ var result0 = result2;
 3124+ } else {
 3125+ var result1 = parse_upperCaseLetter();
 3126+ if (result1 !== null) {
 3127+ var result0 = result1;
 3128+ } else {
 3129+ var result0 = null;;
 3130+ };
 3131+ }
 3132+
 3133+
 3134+
 3135+ cache[cacheKey] = {
 3136+ nextPos: pos,
 3137+ result: result0
 3138+ };
 3139+ return result0;
 3140+ }
 3141+
 3142+ function parse_lowerCaseLetter() {
 3143+ var cacheKey = 'lowerCaseLetter@' + pos;
 3144+ var cachedResult = cache[cacheKey];
 3145+ if (cachedResult) {
 3146+ pos = cachedResult.nextPos;
 3147+ return cachedResult.result;
 3148+ }
 3149+
 3150+
 3151+ if (input.substr(pos).match(/^[a-z]/) !== null) {
 3152+ var result0 = input.charAt(pos);
 3153+ pos++;
 3154+ } else {
 3155+ var result0 = null;
 3156+ if (reportMatchFailures) {
 3157+ matchFailed("[a-z]");
 3158+ }
 3159+ }
 3160+
 3161+
 3162+
 3163+ cache[cacheKey] = {
 3164+ nextPos: pos,
 3165+ result: result0
 3166+ };
 3167+ return result0;
 3168+ }
 3169+
 3170+ function parse_upperCaseLetter() {
 3171+ var cacheKey = 'upperCaseLetter@' + pos;
 3172+ var cachedResult = cache[cacheKey];
 3173+ if (cachedResult) {
 3174+ pos = cachedResult.nextPos;
 3175+ return cachedResult.result;
 3176+ }
 3177+
 3178+
 3179+ if (input.substr(pos).match(/^[A-Z]/) !== null) {
 3180+ var result0 = input.charAt(pos);
 3181+ pos++;
 3182+ } else {
 3183+ var result0 = null;
 3184+ if (reportMatchFailures) {
 3185+ matchFailed("[A-Z]");
 3186+ }
 3187+ }
 3188+
 3189+
 3190+
 3191+ cache[cacheKey] = {
 3192+ nextPos: pos,
 3193+ result: result0
 3194+ };
 3195+ return result0;
 3196+ }
 3197+
 3198+ function parse___() {
 3199+ var cacheKey = '__@' + pos;
 3200+ var cachedResult = cache[cacheKey];
 3201+ if (cachedResult) {
 3202+ pos = cachedResult.nextPos;
 3203+ return cachedResult.result;
 3204+ }
 3205+
 3206+
 3207+ var result0 = [];
 3208+ var result4 = parse_whitespace();
 3209+ if (result4 !== null) {
 3210+ var result1 = result4;
 3211+ } else {
 3212+ var result3 = parse_eol();
 3213+ if (result3 !== null) {
 3214+ var result1 = result3;
 3215+ } else {
 3216+ var result2 = parse_comment();
 3217+ if (result2 !== null) {
 3218+ var result1 = result2;
 3219+ } else {
 3220+ var result1 = null;;
 3221+ };
 3222+ };
 3223+ }
 3224+ while (result1 !== null) {
 3225+ result0.push(result1);
 3226+ var result4 = parse_whitespace();
 3227+ if (result4 !== null) {
 3228+ var result1 = result4;
 3229+ } else {
 3230+ var result3 = parse_eol();
 3231+ if (result3 !== null) {
 3232+ var result1 = result3;
 3233+ } else {
 3234+ var result2 = parse_comment();
 3235+ if (result2 !== null) {
 3236+ var result1 = result2;
 3237+ } else {
 3238+ var result1 = null;;
 3239+ };
 3240+ };
 3241+ }
 3242+ }
 3243+
 3244+
 3245+
 3246+ cache[cacheKey] = {
 3247+ nextPos: pos,
 3248+ result: result0
 3249+ };
 3250+ return result0;
 3251+ }
 3252+
 3253+ function parse_comment() {
 3254+ var cacheKey = 'comment@' + pos;
 3255+ var cachedResult = cache[cacheKey];
 3256+ if (cachedResult) {
 3257+ pos = cachedResult.nextPos;
 3258+ return cachedResult.result;
 3259+ }
 3260+
 3261+ var savedReportMatchFailures = reportMatchFailures;
 3262+ reportMatchFailures = false;
 3263+ var result2 = parse_singleLineComment();
 3264+ if (result2 !== null) {
 3265+ var result0 = result2;
 3266+ } else {
 3267+ var result1 = parse_multiLineComment();
 3268+ if (result1 !== null) {
 3269+ var result0 = result1;
 3270+ } else {
 3271+ var result0 = null;;
 3272+ };
 3273+ }
 3274+ reportMatchFailures = savedReportMatchFailures;
 3275+ if (reportMatchFailures && result0 === null) {
 3276+ matchFailed("comment");
 3277+ }
 3278+
 3279+ cache[cacheKey] = {
 3280+ nextPos: pos,
 3281+ result: result0
 3282+ };
 3283+ return result0;
 3284+ }
 3285+
 3286+ function parse_singleLineComment() {
 3287+ var cacheKey = 'singleLineComment@' + pos;
 3288+ var cachedResult = cache[cacheKey];
 3289+ if (cachedResult) {
 3290+ pos = cachedResult.nextPos;
 3291+ return cachedResult.result;
 3292+ }
 3293+
 3294+
 3295+ var savedPos0 = pos;
 3296+ if (input.substr(pos, 2) === "//") {
 3297+ var result1 = "//";
 3298+ pos += 2;
 3299+ } else {
 3300+ var result1 = null;
 3301+ if (reportMatchFailures) {
 3302+ matchFailed("\"//\"");
 3303+ }
 3304+ }
 3305+ if (result1 !== null) {
 3306+ var result2 = [];
 3307+ var savedPos1 = pos;
 3308+ var savedPos2 = pos;
 3309+ var savedReportMatchFailuresVar0 = reportMatchFailures;
 3310+ reportMatchFailures = false;
 3311+ var result6 = parse_eolChar();
 3312+ reportMatchFailures = savedReportMatchFailuresVar0;
 3313+ if (result6 === null) {
 3314+ var result4 = '';
 3315+ } else {
 3316+ var result4 = null;
 3317+ pos = savedPos2;
 3318+ }
 3319+ if (result4 !== null) {
 3320+ if (input.length > pos) {
 3321+ var result5 = input.charAt(pos);
 3322+ pos++;
 3323+ } else {
 3324+ var result5 = null;
 3325+ if (reportMatchFailures) {
 3326+ matchFailed('any character');
 3327+ }
 3328+ }
 3329+ if (result5 !== null) {
 3330+ var result3 = [result4, result5];
 3331+ } else {
 3332+ var result3 = null;
 3333+ pos = savedPos1;
 3334+ }
 3335+ } else {
 3336+ var result3 = null;
 3337+ pos = savedPos1;
 3338+ }
 3339+ while (result3 !== null) {
 3340+ result2.push(result3);
 3341+ var savedPos1 = pos;
 3342+ var savedPos2 = pos;
 3343+ var savedReportMatchFailuresVar0 = reportMatchFailures;
 3344+ reportMatchFailures = false;
 3345+ var result6 = parse_eolChar();
 3346+ reportMatchFailures = savedReportMatchFailuresVar0;
 3347+ if (result6 === null) {
 3348+ var result4 = '';
 3349+ } else {
 3350+ var result4 = null;
 3351+ pos = savedPos2;
 3352+ }
 3353+ if (result4 !== null) {
 3354+ if (input.length > pos) {
 3355+ var result5 = input.charAt(pos);
 3356+ pos++;
 3357+ } else {
 3358+ var result5 = null;
 3359+ if (reportMatchFailures) {
 3360+ matchFailed('any character');
 3361+ }
 3362+ }
 3363+ if (result5 !== null) {
 3364+ var result3 = [result4, result5];
 3365+ } else {
 3366+ var result3 = null;
 3367+ pos = savedPos1;
 3368+ }
 3369+ } else {
 3370+ var result3 = null;
 3371+ pos = savedPos1;
 3372+ }
 3373+ }
 3374+ if (result2 !== null) {
 3375+ var result0 = [result1, result2];
 3376+ } else {
 3377+ var result0 = null;
 3378+ pos = savedPos0;
 3379+ }
 3380+ } else {
 3381+ var result0 = null;
 3382+ pos = savedPos0;
 3383+ }
 3384+
 3385+
 3386+
 3387+ cache[cacheKey] = {
 3388+ nextPos: pos,
 3389+ result: result0
 3390+ };
 3391+ return result0;
 3392+ }
 3393+
 3394+ function parse_multiLineComment() {
 3395+ var cacheKey = 'multiLineComment@' + pos;
 3396+ var cachedResult = cache[cacheKey];
 3397+ if (cachedResult) {
 3398+ pos = cachedResult.nextPos;
 3399+ return cachedResult.result;
 3400+ }
 3401+
 3402+
 3403+ var savedPos0 = pos;
 3404+ if (input.substr(pos, 2) === "/*") {
 3405+ var result1 = "/*";
 3406+ pos += 2;
 3407+ } else {
 3408+ var result1 = null;
 3409+ if (reportMatchFailures) {
 3410+ matchFailed("\"/*\"");
 3411+ }
 3412+ }
 3413+ if (result1 !== null) {
 3414+ var result2 = [];
 3415+ var savedPos1 = pos;
 3416+ var savedPos2 = pos;
 3417+ var savedReportMatchFailuresVar0 = reportMatchFailures;
 3418+ reportMatchFailures = false;
 3419+ if (input.substr(pos, 2) === "*/") {
 3420+ var result7 = "*/";
 3421+ pos += 2;
 3422+ } else {
 3423+ var result7 = null;
 3424+ if (reportMatchFailures) {
 3425+ matchFailed("\"*/\"");
 3426+ }
 3427+ }
 3428+ reportMatchFailures = savedReportMatchFailuresVar0;
 3429+ if (result7 === null) {
 3430+ var result5 = '';
 3431+ } else {
 3432+ var result5 = null;
 3433+ pos = savedPos2;
 3434+ }
 3435+ if (result5 !== null) {
 3436+ if (input.length > pos) {
 3437+ var result6 = input.charAt(pos);
 3438+ pos++;
 3439+ } else {
 3440+ var result6 = null;
 3441+ if (reportMatchFailures) {
 3442+ matchFailed('any character');
 3443+ }
 3444+ }
 3445+ if (result6 !== null) {
 3446+ var result4 = [result5, result6];
 3447+ } else {
 3448+ var result4 = null;
 3449+ pos = savedPos1;
 3450+ }
 3451+ } else {
 3452+ var result4 = null;
 3453+ pos = savedPos1;
 3454+ }
 3455+ while (result4 !== null) {
 3456+ result2.push(result4);
 3457+ var savedPos1 = pos;
 3458+ var savedPos2 = pos;
 3459+ var savedReportMatchFailuresVar0 = reportMatchFailures;
 3460+ reportMatchFailures = false;
 3461+ if (input.substr(pos, 2) === "*/") {
 3462+ var result7 = "*/";
 3463+ pos += 2;
 3464+ } else {
 3465+ var result7 = null;
 3466+ if (reportMatchFailures) {
 3467+ matchFailed("\"*/\"");
 3468+ }
 3469+ }
 3470+ reportMatchFailures = savedReportMatchFailuresVar0;
 3471+ if (result7 === null) {
 3472+ var result5 = '';
 3473+ } else {
 3474+ var result5 = null;
 3475+ pos = savedPos2;
 3476+ }
 3477+ if (result5 !== null) {
 3478+ if (input.length > pos) {
 3479+ var result6 = input.charAt(pos);
 3480+ pos++;
 3481+ } else {
 3482+ var result6 = null;
 3483+ if (reportMatchFailures) {
 3484+ matchFailed('any character');
 3485+ }
 3486+ }
 3487+ if (result6 !== null) {
 3488+ var result4 = [result5, result6];
 3489+ } else {
 3490+ var result4 = null;
 3491+ pos = savedPos1;
 3492+ }
 3493+ } else {
 3494+ var result4 = null;
 3495+ pos = savedPos1;
 3496+ }
 3497+ }
 3498+ if (result2 !== null) {
 3499+ if (input.substr(pos, 2) === "*/") {
 3500+ var result3 = "*/";
 3501+ pos += 2;
 3502+ } else {
 3503+ var result3 = null;
 3504+ if (reportMatchFailures) {
 3505+ matchFailed("\"*/\"");
 3506+ }
 3507+ }
 3508+ if (result3 !== null) {
 3509+ var result0 = [result1, result2, result3];
 3510+ } else {
 3511+ var result0 = null;
 3512+ pos = savedPos0;
 3513+ }
 3514+ } else {
 3515+ var result0 = null;
 3516+ pos = savedPos0;
 3517+ }
 3518+ } else {
 3519+ var result0 = null;
 3520+ pos = savedPos0;
 3521+ }
 3522+
 3523+
 3524+
 3525+ cache[cacheKey] = {
 3526+ nextPos: pos,
 3527+ result: result0
 3528+ };
 3529+ return result0;
 3530+ }
 3531+
 3532+ function parse_eol() {
 3533+ var cacheKey = 'eol@' + pos;
 3534+ var cachedResult = cache[cacheKey];
 3535+ if (cachedResult) {
 3536+ pos = cachedResult.nextPos;
 3537+ return cachedResult.result;
 3538+ }
 3539+
 3540+ var savedReportMatchFailures = reportMatchFailures;
 3541+ reportMatchFailures = false;
 3542+ if (input.substr(pos, 1) === "\n") {
 3543+ var result5 = "\n";
 3544+ pos += 1;
 3545+ } else {
 3546+ var result5 = null;
 3547+ if (reportMatchFailures) {
 3548+ matchFailed("\"\\n\"");
 3549+ }
 3550+ }
 3551+ if (result5 !== null) {
 3552+ var result0 = result5;
 3553+ } else {
 3554+ if (input.substr(pos, 2) === "\r\n") {
 3555+ var result4 = "\r\n";
 3556+ pos += 2;
 3557+ } else {
 3558+ var result4 = null;
 3559+ if (reportMatchFailures) {
 3560+ matchFailed("\"\\r\\n\"");
 3561+ }
 3562+ }
 3563+ if (result4 !== null) {
 3564+ var result0 = result4;
 3565+ } else {
 3566+ if (input.substr(pos, 1) === "\r") {
 3567+ var result3 = "\r";
 3568+ pos += 1;
 3569+ } else {
 3570+ var result3 = null;
 3571+ if (reportMatchFailures) {
 3572+ matchFailed("\"\\r\"");
 3573+ }
 3574+ }
 3575+ if (result3 !== null) {
 3576+ var result0 = result3;
 3577+ } else {
 3578+ if (input.substr(pos, 1) === "\u2028") {
 3579+ var result2 = "\u2028";
 3580+ pos += 1;
 3581+ } else {
 3582+ var result2 = null;
 3583+ if (reportMatchFailures) {
 3584+ matchFailed("\"\\u2028\"");
 3585+ }
 3586+ }
 3587+ if (result2 !== null) {
 3588+ var result0 = result2;
 3589+ } else {
 3590+ if (input.substr(pos, 1) === "\u2029") {
 3591+ var result1 = "\u2029";
 3592+ pos += 1;
 3593+ } else {
 3594+ var result1 = null;
 3595+ if (reportMatchFailures) {
 3596+ matchFailed("\"\\u2029\"");
 3597+ }
 3598+ }
 3599+ if (result1 !== null) {
 3600+ var result0 = result1;
 3601+ } else {
 3602+ var result0 = null;;
 3603+ };
 3604+ };
 3605+ };
 3606+ };
 3607+ }
 3608+ reportMatchFailures = savedReportMatchFailures;
 3609+ if (reportMatchFailures && result0 === null) {
 3610+ matchFailed("end of line");
 3611+ }
 3612+
 3613+ cache[cacheKey] = {
 3614+ nextPos: pos,
 3615+ result: result0
 3616+ };
 3617+ return result0;
 3618+ }
 3619+
 3620+ function parse_eolChar() {
 3621+ var cacheKey = 'eolChar@' + pos;
 3622+ var cachedResult = cache[cacheKey];
 3623+ if (cachedResult) {
 3624+ pos = cachedResult.nextPos;
 3625+ return cachedResult.result;
 3626+ }
 3627+
 3628+
 3629+ if (input.substr(pos).match(/^[\n\r\u2028\u2029]/) !== null) {
 3630+ var result0 = input.charAt(pos);
 3631+ pos++;
 3632+ } else {
 3633+ var result0 = null;
 3634+ if (reportMatchFailures) {
 3635+ matchFailed("[\\n\\r\\u2028\\u2029]");
 3636+ }
 3637+ }
 3638+
 3639+
 3640+
 3641+ cache[cacheKey] = {
 3642+ nextPos: pos,
 3643+ result: result0
 3644+ };
 3645+ return result0;
 3646+ }
 3647+
 3648+ function parse_whitespace() {
 3649+ var cacheKey = 'whitespace@' + pos;
 3650+ var cachedResult = cache[cacheKey];
 3651+ if (cachedResult) {
 3652+ pos = cachedResult.nextPos;
 3653+ return cachedResult.result;
 3654+ }
 3655+
 3656+ var savedReportMatchFailures = reportMatchFailures;
 3657+ reportMatchFailures = false;
 3658+ if (input.substr(pos).match(/^[ ��\xA0\uFEFF\u1680\u180E\u2000-\u200A\u202F\u205F\u3000]/) !== null) {
 3659+ var result0 = input.charAt(pos);
 3660+ pos++;
 3661+ } else {
 3662+ var result0 = null;
 3663+ if (reportMatchFailures) {
 3664+ matchFailed("[ ��\\xA0\\uFEFF\\u1680\\u180E\\u2000-\\u200A\\u202F\\u205F\\u3000]");
 3665+ }
 3666+ }
 3667+ reportMatchFailures = savedReportMatchFailures;
 3668+ if (reportMatchFailures && result0 === null) {
 3669+ matchFailed("whitespace");
 3670+ }
 3671+
 3672+ cache[cacheKey] = {
 3673+ nextPos: pos,
 3674+ result: result0
 3675+ };
 3676+ return result0;
 3677+ }
 3678+
 3679+ function buildErrorMessage() {
 3680+ function buildExpected(failuresExpected) {
 3681+ failuresExpected.sort();
 3682+
 3683+ var lastFailure = null;
 3684+ var failuresExpectedUnique = [];
 3685+ for (var i = 0; i < failuresExpected.length; i++) {
 3686+ if (failuresExpected[i] !== lastFailure) {
 3687+ failuresExpectedUnique.push(failuresExpected[i]);
 3688+ lastFailure = failuresExpected[i];
 3689+ }
 3690+ }
 3691+
 3692+ switch (failuresExpectedUnique.length) {
 3693+ case 0:
 3694+ return 'end of input';
 3695+ case 1:
 3696+ return failuresExpectedUnique[0];
 3697+ default:
 3698+ return failuresExpectedUnique.slice(0, failuresExpectedUnique.length - 1).join(', ')
 3699+ + ' or '
 3700+ + failuresExpectedUnique[failuresExpectedUnique.length - 1];
 3701+ }
 3702+ }
 3703+
 3704+ var expected = buildExpected(rightmostMatchFailuresExpected);
 3705+ var actualPos = Math.max(pos, rightmostMatchFailuresPos);
 3706+ var actual = actualPos < input.length
 3707+ ? quote(input.charAt(actualPos))
 3708+ : 'end of input';
 3709+
 3710+ return 'Expected ' + expected + ' but ' + actual + ' found.';
 3711+ }
 3712+
 3713+ function computeErrorPosition() {
 3714+ /*
 3715+ * The first idea was to use |String.split| to break the input up to the
 3716+ * error position along newlines and derive the line and column from
 3717+ * there. However IE's |split| implementation is so broken that it was
 3718+ * enough to prevent it.
 3719+ */
 3720+
 3721+ var line = 1;
 3722+ var column = 1;
 3723+ var seenCR = false;
 3724+
 3725+ for (var i = 0; i < rightmostMatchFailuresPos; i++) {
 3726+ var ch = input.charAt(i);
 3727+ if (ch === '\n') {
 3728+ if (!seenCR) { line++; }
 3729+ column = 1;
 3730+ seenCR = false;
 3731+ } else if (ch === '\r' | ch === '\u2028' || ch === '\u2029') {
 3732+ line++;
 3733+ column = 1;
 3734+ seenCR = true;
 3735+ } else {
 3736+ column++;
 3737+ seenCR = false;
 3738+ }
 3739+ }
 3740+
 3741+ return { line: line, column: column };
 3742+ }
 3743+
 3744+
 3745+
 3746+ var result = parseFunctions[startRule]();
 3747+
 3748+ /*
 3749+ * The parser is now in one of the following three states:
 3750+ *
 3751+ * 1. The parser successfully parsed the whole input.
 3752+ *
 3753+ * - |result !== null|
 3754+ * - |pos === input.length|
 3755+ * - |rightmostMatchFailuresExpected| may or may not contain something
 3756+ *
 3757+ * 2. The parser successfully parsed only a part of the input.
 3758+ *
 3759+ * - |result !== null|
 3760+ * - |pos < input.length|
 3761+ * - |rightmostMatchFailuresExpected| may or may not contain something
 3762+ *
 3763+ * 3. The parser did not successfully parse any part of the input.
 3764+ *
 3765+ * - |result === null|
 3766+ * - |pos === 0|
 3767+ * - |rightmostMatchFailuresExpected| contains at least one failure
 3768+ *
 3769+ * All code following this comment (including called functions) must
 3770+ * handle these states.
 3771+ */
 3772+ if (result === null || pos !== input.length) {
 3773+ var errorPosition = computeErrorPosition();
 3774+ throw new this.SyntaxError(
 3775+ buildErrorMessage(),
 3776+ errorPosition.line,
 3777+ errorPosition.column
 3778+ );
 3779+ }
 3780+
 3781+ return result;
 3782+ },
 3783+
 3784+ /* Returns the parser source code. */
 3785+ toSource: function() { return this._source; }
 3786+ };
 3787+
 3788+ /* Thrown when a parser encounters a syntax error. */
 3789+
 3790+ result.SyntaxError = function(message, line, column) {
 3791+ this.name = 'SyntaxError';
 3792+ this.message = message;
 3793+ this.line = line;
 3794+ this.column = column;
 3795+ };
 3796+
 3797+ result.SyntaxError.prototype = Error.prototype;
 3798+
 3799+ return result;
 3800+})();
 3801+PEG.compiler = {
 3802+ /*
 3803+ * Generates a parser from a specified grammar AST. Throws |PEG.GrammarError|
 3804+ * if the AST contains a semantic error. Note that not all errors are detected
 3805+ * during the generation and some may protrude to the generated parser and
 3806+ * cause its malfunction.
 3807+ */
 3808+ compile: function(ast) {
 3809+ var CHECK_NAMES = [
 3810+ "missingReferencedRules",
 3811+ "leftRecursion"
 3812+ ];
 3813+
 3814+ var PASS_NAMES = [
 3815+ "proxyRules"
 3816+ ];
 3817+
 3818+ for (var i = 0; i < CHECK_NAMES.length; i++) {
 3819+ this.checks[CHECK_NAMES[i]](ast);
 3820+ }
 3821+
 3822+ for (var i = 0; i < PASS_NAMES.length; i++) {
 3823+ ast = this.passes[PASS_NAMES[i]](ast);
 3824+ }
 3825+
 3826+ var source = this.emitter(ast);
 3827+ var result = eval(source);
 3828+ result._source = source;
 3829+
 3830+ return result;
 3831+ }
 3832+};
 3833+
 3834+/*
 3835+ * Checks made on the grammar AST before compilation. Each check is a function
 3836+ * that is passed the AST and does not return anything. If the check passes, the
 3837+ * function does not do anything special, otherwise it throws
 3838+ * |PEG.GrammarError|. The order in which the checks are run is specified in
 3839+ * |PEG.compiler.compile| and should be the same as the order of definitions
 3840+ * here.
 3841+ */
 3842+PEG.compiler.checks = {
 3843+ /* Checks that all referenced rules exist. */
 3844+ missingReferencedRules: function(ast) {
 3845+ function nop() {}
 3846+
 3847+ function checkExpression(node) { check(node.expression); }
 3848+
 3849+ function checkSubnodes(propertyName) {
 3850+ return function(node) { each(node[propertyName], check); };
 3851+ }
 3852+
 3853+ var check = buildNodeVisitor({
 3854+ grammar:
 3855+ function(node) {
 3856+ for (var name in node.rules) {
 3857+ check(node.rules[name]);
 3858+ }
 3859+ },
 3860+
 3861+ rule: checkExpression,
 3862+ choice: checkSubnodes("alternatives"),
 3863+ sequence: checkSubnodes("elements"),
 3864+ labeled: checkExpression,
 3865+ simple_and: checkExpression,
 3866+ simple_not: checkExpression,
 3867+ semantic_and: nop,
 3868+ semantic_not: nop,
 3869+ optional: checkExpression,
 3870+ zero_or_more: checkExpression,
 3871+ one_or_more: checkExpression,
 3872+ action: checkExpression,
 3873+
 3874+ rule_ref:
 3875+ function(node) {
 3876+ if (ast.rules[node.name] === undefined) {
 3877+ throw new PEG.GrammarError(
 3878+ "Referenced rule \"" + node.name + "\" does not exist."
 3879+ );
 3880+ }
 3881+ },
 3882+
 3883+ literal: nop,
 3884+ any: nop,
 3885+ "class": nop
 3886+ });
 3887+
 3888+ check(ast);
 3889+ },
 3890+
 3891+ /* Checks that no left recursion is present. */
 3892+ leftRecursion: function(ast) {
 3893+ function nop() {}
 3894+
 3895+ function checkExpression(node, appliedRules) {
 3896+ check(node.expression, appliedRules);
 3897+ }
 3898+
 3899+ var check = buildNodeVisitor({
 3900+ grammar:
 3901+ function(node, appliedRules) {
 3902+ for (var name in node.rules) {
 3903+ check(node.rules[name], appliedRules);
 3904+ }
 3905+ },
 3906+
 3907+ rule:
 3908+ function(node, appliedRules) {
 3909+ check(node.expression, appliedRules.concat(node.name));
 3910+ },
 3911+
 3912+ choice:
 3913+ function(node, appliedRules) {
 3914+ each(node.alternatives, function(alternative) {
 3915+ check(alternative, appliedRules);
 3916+ });
 3917+ },
 3918+
 3919+ sequence:
 3920+ function(node, appliedRules) {
 3921+ if (node.elements.length > 0) {
 3922+ check(node.elements[0], appliedRules);
 3923+ }
 3924+ },
 3925+
 3926+ labeled: checkExpression,
 3927+ simple_and: checkExpression,
 3928+ simple_not: checkExpression,
 3929+ semantic_and: nop,
 3930+ semantic_not: nop,
 3931+ optional: checkExpression,
 3932+ zero_or_more: checkExpression,
 3933+ one_or_more: checkExpression,
 3934+ action: checkExpression,
 3935+
 3936+ rule_ref:
 3937+ function(node, appliedRules) {
 3938+ if (contains(appliedRules, node.name)) {
 3939+ throw new PEG.GrammarError(
 3940+ "Left recursion detected for rule \"" + node.name + "\"."
 3941+ );
 3942+ }
 3943+ check(ast.rules[node.name], appliedRules);
 3944+ },
 3945+
 3946+ literal: nop,
 3947+ any: nop,
 3948+ "class": nop
 3949+ });
 3950+
 3951+ check(ast, []);
 3952+ }
 3953+};
 3954+/*
 3955+ * Optimalization passes made on the grammar AST before compilation. Each pass
 3956+ * is a function that is passed the AST and returns a new AST. The AST can be
 3957+ * modified in-place by the pass. The order in which the passes are run is
 3958+ * specified in |PEG.compiler.compile| and should be the same as the order of
 3959+ * definitions here.
 3960+ */
 3961+PEG.compiler.passes = {
 3962+ /*
 3963+ * Removes proxy rules -- that is, rules that only delegate to other rule.
 3964+ */
 3965+ proxyRules: function(ast) {
 3966+ function isProxyRule(node) {
 3967+ return node.type === "rule" && node.expression.type === "rule_ref";
 3968+ }
 3969+
 3970+ function replaceRuleRefs(ast, from, to) {
 3971+ function nop() {}
 3972+
 3973+ function replaceInExpression(node, from, to) {
 3974+ replace(node.expression, from, to);
 3975+ }
 3976+
 3977+ function replaceInSubnodes(propertyName) {
 3978+ return function(node, from, to) {
 3979+ each(node[propertyName], function(subnode) {
 3980+ replace(subnode, from, to);
 3981+ });
 3982+ };
 3983+ }
 3984+
 3985+ var replace = buildNodeVisitor({
 3986+ grammar:
 3987+ function(node, from, to) {
 3988+ for (var name in node.rules) {
 3989+ replace(node.rules[name], from, to);
 3990+ }
 3991+ },
 3992+
 3993+ rule: replaceInExpression,
 3994+ choice: replaceInSubnodes("alternatives"),
 3995+ sequence: replaceInSubnodes("elements"),
 3996+ labeled: replaceInExpression,
 3997+ simple_and: replaceInExpression,
 3998+ simple_not: replaceInExpression,
 3999+ semantic_and: nop,
 4000+ semantic_not: nop,
 4001+ optional: replaceInExpression,
 4002+ zero_or_more: replaceInExpression,
 4003+ one_or_more: replaceInExpression,
 4004+ action: replaceInExpression,
 4005+
 4006+ rule_ref:
 4007+ function(node, from, to) {
 4008+ if (node.name === from) {
 4009+ node.name = to;
 4010+ }
 4011+ },
 4012+
 4013+ literal: nop,
 4014+ any: nop,
 4015+ "class": nop
 4016+ });
 4017+
 4018+ replace(ast, from, to);
 4019+ }
 4020+
 4021+ for (var name in ast.rules) {
 4022+ if (isProxyRule(ast.rules[name])) {
 4023+ replaceRuleRefs(ast, ast.rules[name].name, ast.rules[name].expression.name);
 4024+ if (name === ast.startRule) {
 4025+ ast.startRule = ast.rules[name].expression.name;
 4026+ }
 4027+ delete ast.rules[name];
 4028+ }
 4029+ }
 4030+
 4031+ return ast;
 4032+ }
 4033+};
 4034+/* Emits the generated code for the AST. */
 4035+PEG.compiler.emitter = function(ast) {
 4036+ /*
 4037+ * Takes parts of code, interpolates variables inside them and joins them with
 4038+ * a newline.
 4039+ *
 4040+ * Variables are delimited with "${" and "}" and their names must be valid
 4041+ * identifiers (i.e. they must match [a-zA-Z_][a-zA-Z0-9_]*). Variable values
 4042+ * are specified as properties of the last parameter (if this is an object,
 4043+ * otherwise empty variable set is assumed). Undefined variables result in
 4044+ * throwing |Error|.
 4045+ *
 4046+ * There can be a filter specified after the variable name, prefixed with "|".
 4047+ * The filter name must be a valid identifier. The only recognized filter
 4048+ * right now is "string", which quotes the variable value as a JavaScript
 4049+ * string. Unrecognized filters result in throwing |Error|.
 4050+ *
 4051+ * If any part has multiple lines and the first line is indented by some
 4052+ * amount of whitespace (as defined by the /\s+/ JavaScript regular
 4053+ * expression), second to last lines are indented by the same amount of
 4054+ * whitespace. This results in nicely indented multiline code in variables
 4055+ * without making the templates look ugly.
 4056+ *
 4057+ * Examples:
 4058+ *
 4059+ * formatCode("foo", "bar"); // "foo\nbar"
 4060+ * formatCode("foo", "${bar}", { bar: "baz" }); // "foo\nbaz"
 4061+ * formatCode("foo", "${bar}"); // throws Error
 4062+ * formatCode("foo", "${bar|string}", { bar: "baz" }); // "foo\n\"baz\""
 4063+ * formatCode("foo", "${bar|eeek}", { bar: "baz" }); // throws Error
 4064+ * formatCode("foo", "${bar}", { bar: " baz\nqux" }); // "foo\n baz\n qux"
 4065+ */
 4066+ function formatCode() {
 4067+ function interpolateVariablesInParts(parts) {
 4068+ return map(parts, function(part) {
 4069+ return part.replace(
 4070+ /\$\{([a-zA-Z_][a-zA-Z0-9_]*)(\|([a-zA-Z_][a-zA-Z0-9_]*))?\}/g,
 4071+ function(match, name, dummy, filter) {
 4072+ var value = vars[name];
 4073+ if (value === undefined) {
 4074+ throw new Error("Undefined variable: \"" + name + "\".");
 4075+ }
 4076+
 4077+ if (filter !== undefined && filter != "") { // JavaScript engines differ here.
 4078+ if (filter === "string") {
 4079+ return quote(value);
 4080+ } else {
 4081+ throw new Error("Unrecognized filter: \"" + filter + "\".");
 4082+ }
 4083+ } else {
 4084+ return value;
 4085+ }
 4086+ }
 4087+ );
 4088+ });
 4089+ }
 4090+
 4091+ function indentMultilineParts(parts) {
 4092+ return map(parts, function(part) {
 4093+ if (!/\n/.test(part)) { return part; }
 4094+
 4095+ var firstLineWhitespacePrefix = part.match(/^\s*/)[0];
 4096+ var lines = part.split("\n");
 4097+ var linesIndented = [lines[0]].concat(
 4098+ map(lines.slice(1), function(line) {
 4099+ return firstLineWhitespacePrefix + line;
 4100+ })
 4101+ );
 4102+ return linesIndented.join("\n");
 4103+ });
 4104+ }
 4105+
 4106+ var args = Array.prototype.slice.call(arguments);
 4107+ var vars = args[args.length - 1] instanceof Object ? args.pop() : {};
 4108+
 4109+ return indentMultilineParts(interpolateVariablesInParts(args)).join("\n");
 4110+ };
 4111+
 4112+ /* Unique ID generator. */
 4113+ var UID = {
 4114+ _counters: {},
 4115+
 4116+ next: function(prefix) {
 4117+ this._counters[prefix] = this._counters[prefix] || 0;
 4118+ return prefix + this._counters[prefix]++;
 4119+ },
 4120+
 4121+ reset: function() {
 4122+ this._counters = {};
 4123+ }
 4124+ };
 4125+
 4126+ var emit = buildNodeVisitor({
 4127+ grammar: function(node) {
 4128+ var initializerCode = node.initializer !== null
 4129+ ? emit(node.initializer)
 4130+ : "";
 4131+
 4132+ var parseFunctionTableItems = [];
 4133+ for (var name in node.rules) {
 4134+ parseFunctionTableItems.push(quote(name) + ": parse_" + name);
 4135+ }
 4136+ parseFunctionTableItems.sort();
 4137+
 4138+ var parseFunctionDefinitions = [];
 4139+ for (var name in node.rules) {
 4140+ parseFunctionDefinitions.push(emit(node.rules[name]));
 4141+ }
 4142+
 4143+ return formatCode(
 4144+ "(function(){",
 4145+ " /* Generated by PEG.js 0.6.1 (http://pegjs.majda.cz/). */",
 4146+ " ",
 4147+ " var result = {",
 4148+ " /*",
 4149+ " * Parses the input with a generated parser. If the parsing is successfull,",
 4150+ " * returns a value explicitly or implicitly specified by the grammar from",
 4151+ " * which the parser was generated (see |PEG.buildParser|). If the parsing is",
 4152+ " * unsuccessful, throws |PEG.parser.SyntaxError| describing the error.",
 4153+ " */",
 4154+ " parse: function(input, startRule) {",
 4155+ " var parseFunctions = {",
 4156+ " ${parseFunctionTableItems}",
 4157+ " };",
 4158+ " ",
 4159+ " if (startRule !== undefined) {",
 4160+ " if (parseFunctions[startRule] === undefined) {",
 4161+ " throw new Error(\"Invalid rule name: \" + quote(startRule) + \".\");",
 4162+ " }",
 4163+ " } else {",
 4164+ " startRule = ${startRule|string};",
 4165+ " }",
 4166+ " ",
 4167+ " var pos = 0;",
 4168+ " var reportMatchFailures = true;",
 4169+ " var rightmostMatchFailuresPos = 0;",
 4170+ " var rightmostMatchFailuresExpected = [];",
 4171+ " var cache = {};",
 4172+ " ",
 4173+ /* This needs to be in sync with |padLeft| in utils.js. */
 4174+ " function padLeft(input, padding, length) {",
 4175+ " var result = input;",
 4176+ " ",
 4177+ " var padLength = length - input.length;",
 4178+ " for (var i = 0; i < padLength; i++) {",
 4179+ " result = padding + result;",
 4180+ " }",
 4181+ " ",
 4182+ " return result;",
 4183+ " }",
 4184+ " ",
 4185+ /* This needs to be in sync with |escape| in utils.js. */
 4186+ " function escape(ch) {",
 4187+ " var charCode = ch.charCodeAt(0);",
 4188+ " ",
 4189+ " if (charCode <= 0xFF) {",
 4190+ " var escapeChar = 'x';",
 4191+ " var length = 2;",
 4192+ " } else {",
 4193+ " var escapeChar = 'u';",
 4194+ " var length = 4;",
 4195+ " }",
 4196+ " ",
 4197+ " return '\\\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length);",
 4198+ " }",
 4199+ " ",
 4200+ /* This needs to be in sync with |quote| in utils.js. */
 4201+ " function quote(s) {",
 4202+ " /*",
 4203+ " * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a",
 4204+ " * string literal except for the closing quote character, backslash,",
 4205+ " * carriage return, line separator, paragraph separator, and line feed.",
 4206+ " * Any character may appear in the form of an escape sequence.",
 4207+ " */",
 4208+ " return '\"' + s",
 4209+ " .replace(/\\\\/g, '\\\\\\\\') // backslash",
 4210+ " .replace(/\"/g, '\\\\\"') // closing quote character",
 4211+ " .replace(/\\r/g, '\\\\r') // carriage return",
 4212+ " .replace(/\\n/g, '\\\\n') // line feed",
 4213+ " .replace(/[\\x80-\\uFFFF]/g, escape) // non-ASCII characters",
 4214+ " + '\"';",
 4215+ " }",
 4216+ " ",
 4217+ " function matchFailed(failure) {",
 4218+ " if (pos < rightmostMatchFailuresPos) {",
 4219+ " return;",
 4220+ " }",
 4221+ " ",
 4222+ " if (pos > rightmostMatchFailuresPos) {",
 4223+ " rightmostMatchFailuresPos = pos;",
 4224+ " rightmostMatchFailuresExpected = [];",
 4225+ " }",
 4226+ " ",
 4227+ " rightmostMatchFailuresExpected.push(failure);",
 4228+ " }",
 4229+ " ",
 4230+ " ${parseFunctionDefinitions}",
 4231+ " ",
 4232+ " function buildErrorMessage() {",
 4233+ " function buildExpected(failuresExpected) {",
 4234+ " failuresExpected.sort();",
 4235+ " ",
 4236+ " var lastFailure = null;",
 4237+ " var failuresExpectedUnique = [];",
 4238+ " for (var i = 0; i < failuresExpected.length; i++) {",
 4239+ " if (failuresExpected[i] !== lastFailure) {",
 4240+ " failuresExpectedUnique.push(failuresExpected[i]);",
 4241+ " lastFailure = failuresExpected[i];",
 4242+ " }",
 4243+ " }",
 4244+ " ",
 4245+ " switch (failuresExpectedUnique.length) {",
 4246+ " case 0:",
 4247+ " return 'end of input';",
 4248+ " case 1:",
 4249+ " return failuresExpectedUnique[0];",
 4250+ " default:",
 4251+ " return failuresExpectedUnique.slice(0, failuresExpectedUnique.length - 1).join(', ')",
 4252+ " + ' or '",
 4253+ " + failuresExpectedUnique[failuresExpectedUnique.length - 1];",
 4254+ " }",
 4255+ " }",
 4256+ " ",
 4257+ " var expected = buildExpected(rightmostMatchFailuresExpected);",
 4258+ " var actualPos = Math.max(pos, rightmostMatchFailuresPos);",
 4259+ " var actual = actualPos < input.length",
 4260+ " ? quote(input.charAt(actualPos))",
 4261+ " : 'end of input';",
 4262+ " ",
 4263+ " return 'Expected ' + expected + ' but ' + actual + ' found.';",
 4264+ " }",
 4265+ " ",
 4266+ " function computeErrorPosition() {",
 4267+ " /*",
 4268+ " * The first idea was to use |String.split| to break the input up to the",
 4269+ " * error position along newlines and derive the line and column from",
 4270+ " * there. However IE's |split| implementation is so broken that it was",
 4271+ " * enough to prevent it.",
 4272+ " */",
 4273+ " ",
 4274+ " var line = 1;",
 4275+ " var column = 1;",
 4276+ " var seenCR = false;",
 4277+ " ",
 4278+ " for (var i = 0; i < rightmostMatchFailuresPos; i++) {",
 4279+ " var ch = input.charAt(i);",
 4280+ " if (ch === '\\n') {",
 4281+ " if (!seenCR) { line++; }",
 4282+ " column = 1;",
 4283+ " seenCR = false;",
 4284+ " } else if (ch === '\\r' | ch === '\\u2028' || ch === '\\u2029') {",
 4285+ " line++;",
 4286+ " column = 1;",
 4287+ " seenCR = true;",
 4288+ " } else {",
 4289+ " column++;",
 4290+ " seenCR = false;",
 4291+ " }",
 4292+ " }",
 4293+ " ",
 4294+ " return { line: line, column: column };",
 4295+ " }",
 4296+ " ",
 4297+ " ${initializerCode}",
 4298+ " ",
 4299+ " var result = parseFunctions[startRule]();",
 4300+ " ",
 4301+ " /*",
 4302+ " * The parser is now in one of the following three states:",
 4303+ " *",
 4304+ " * 1. The parser successfully parsed the whole input.",
 4305+ " *",
 4306+ " * - |result !== null|",
 4307+ " * - |pos === input.length|",
 4308+ " * - |rightmostMatchFailuresExpected| may or may not contain something",
 4309+ " *",
 4310+ " * 2. The parser successfully parsed only a part of the input.",
 4311+ " *",
 4312+ " * - |result !== null|",
 4313+ " * - |pos < input.length|",
 4314+ " * - |rightmostMatchFailuresExpected| may or may not contain something",
 4315+ " *",
 4316+ " * 3. The parser did not successfully parse any part of the input.",
 4317+ " *",
 4318+ " * - |result === null|",
 4319+ " * - |pos === 0|",
 4320+ " * - |rightmostMatchFailuresExpected| contains at least one failure",
 4321+ " *",
 4322+ " * All code following this comment (including called functions) must",
 4323+ " * handle these states.",
 4324+ " */",
 4325+ " if (result === null || pos !== input.length) {",
 4326+ " var errorPosition = computeErrorPosition();",
 4327+ " throw new this.SyntaxError(",
 4328+ " buildErrorMessage(),",
 4329+ " errorPosition.line,",
 4330+ " errorPosition.column",
 4331+ " );",
 4332+ " }",
 4333+ " ",
 4334+ " return result;",
 4335+ " },",
 4336+ " ",
 4337+ " /* Returns the parser source code. */",
 4338+ " toSource: function() { return this._source; }",
 4339+ " };",
 4340+ " ",
 4341+ " /* Thrown when a parser encounters a syntax error. */",
 4342+ " ",
 4343+ " result.SyntaxError = function(message, line, column) {",
 4344+ " this.name = 'SyntaxError';",
 4345+ " this.message = message;",
 4346+ " this.line = line;",
 4347+ " this.column = column;",
 4348+ " };",
 4349+ " ",
 4350+ " result.SyntaxError.prototype = Error.prototype;",
 4351+ " ",
 4352+ " return result;",
 4353+ "})()",
 4354+ {
 4355+ initializerCode: initializerCode,
 4356+ parseFunctionTableItems: parseFunctionTableItems.join(",\n"),
 4357+ parseFunctionDefinitions: parseFunctionDefinitions.join("\n\n"),
 4358+ startRule: node.startRule
 4359+ }
 4360+ );
 4361+ },
 4362+
 4363+ initializer: function(node) {
 4364+ return node.code;
 4365+ },
 4366+
 4367+ rule: function(node) {
 4368+ /*
 4369+ * We want to reset variable names at the beginning of every function so
 4370+ * that a little change in the source grammar does not change variables in
 4371+ * all the generated code. This is desired especially when one has the
 4372+ * generated grammar stored in a VCS (this is true e.g. for our
 4373+ * metagrammar).
 4374+ */
 4375+ UID.reset();
 4376+
 4377+ var resultVar = UID.next("result");
 4378+
 4379+ if (node.displayName !== null) {
 4380+ var setReportMatchFailuresCode = formatCode(
 4381+ "var savedReportMatchFailures = reportMatchFailures;",
 4382+ "reportMatchFailures = false;"
 4383+ );
 4384+ var restoreReportMatchFailuresCode = formatCode(
 4385+ "reportMatchFailures = savedReportMatchFailures;"
 4386+ );
 4387+ var reportMatchFailureCode = formatCode(
 4388+ "if (reportMatchFailures && ${resultVar} === null) {",
 4389+ " matchFailed(${displayName|string});",
 4390+ "}",
 4391+ {
 4392+ displayName: node.displayName,
 4393+ resultVar: resultVar
 4394+ }
 4395+ );
 4396+ } else {
 4397+ var setReportMatchFailuresCode = "";
 4398+ var restoreReportMatchFailuresCode = "";
 4399+ var reportMatchFailureCode = "";
 4400+ }
 4401+
 4402+ return formatCode(
 4403+ "function parse_${name}() {",
 4404+ " var cacheKey = '${name}@' + pos;",
 4405+ " var cachedResult = cache[cacheKey];",
 4406+ " if (cachedResult) {",
 4407+ " pos = cachedResult.nextPos;",
 4408+ " return cachedResult.result;",
 4409+ " }",
 4410+ " ",
 4411+ " ${setReportMatchFailuresCode}",
 4412+ " ${code}",
 4413+ " ${restoreReportMatchFailuresCode}",
 4414+ " ${reportMatchFailureCode}",
 4415+ " ",
 4416+ " cache[cacheKey] = {",
 4417+ " nextPos: pos,",
 4418+ " result: ${resultVar}",
 4419+ " };",
 4420+ " return ${resultVar};",
 4421+ "}",
 4422+ {
 4423+ name: node.name,
 4424+ setReportMatchFailuresCode: setReportMatchFailuresCode,
 4425+ restoreReportMatchFailuresCode: restoreReportMatchFailuresCode,
 4426+ reportMatchFailureCode: reportMatchFailureCode,
 4427+ code: emit(node.expression, resultVar),
 4428+ resultVar: resultVar
 4429+ }
 4430+ );
 4431+ },
 4432+
 4433+ /*
 4434+ * The contract for all code fragments generated by the following functions
 4435+ * is as follows:
 4436+ *
 4437+ * * The code fragment should try to match a part of the input starting with
 4438+ * the position indicated in |pos|. That position may point past the end of
 4439+ * the input.
 4440+ *
 4441+ * * If the code fragment matches the input, it advances |pos| after the
 4442+ * matched part of the input and sets variable with a name stored in
 4443+ * |resultVar| to appropriate value, which is always non-null.
 4444+ *
 4445+ * * If the code fragment does not match the input, it does not change |pos|
 4446+ * and it sets a variable with a name stored in |resultVar| to |null|.
 4447+ */
 4448+
 4449+ choice: function(node, resultVar) {
 4450+ var code = formatCode(
 4451+ "var ${resultVar} = null;",
 4452+ { resultVar: resultVar }
 4453+ );
 4454+
 4455+ for (var i = node.alternatives.length - 1; i >= 0; i--) {
 4456+ var alternativeResultVar = UID.next("result");
 4457+ code = formatCode(
 4458+ "${alternativeCode}",
 4459+ "if (${alternativeResultVar} !== null) {",
 4460+ " var ${resultVar} = ${alternativeResultVar};",
 4461+ "} else {",
 4462+ " ${code};",
 4463+ "}",
 4464+ {
 4465+ alternativeCode: emit(node.alternatives[i], alternativeResultVar),
 4466+ alternativeResultVar: alternativeResultVar,
 4467+ code: code,
 4468+ resultVar: resultVar
 4469+ }
 4470+ );
 4471+ }
 4472+
 4473+ return code;
 4474+ },
 4475+
 4476+ sequence: function(node, resultVar) {
 4477+ var savedPosVar = UID.next("savedPos");
 4478+
 4479+ var elementResultVars = map(node.elements, function() {
 4480+ return UID.next("result")
 4481+ });
 4482+
 4483+ var code = formatCode(
 4484+ "var ${resultVar} = ${elementResultVarArray};",
 4485+ {
 4486+ resultVar: resultVar,
 4487+ elementResultVarArray: "[" + elementResultVars.join(", ") + "]"
 4488+ }
 4489+ );
 4490+
 4491+ for (var i = node.elements.length - 1; i >= 0; i--) {
 4492+ code = formatCode(
 4493+ "${elementCode}",
 4494+ "if (${elementResultVar} !== null) {",
 4495+ " ${code}",
 4496+ "} else {",
 4497+ " var ${resultVar} = null;",
 4498+ " pos = ${savedPosVar};",
 4499+ "}",
 4500+ {
 4501+ elementCode: emit(node.elements[i], elementResultVars[i]),
 4502+ elementResultVar: elementResultVars[i],
 4503+ code: code,
 4504+ savedPosVar: savedPosVar,
 4505+ resultVar: resultVar
 4506+ }
 4507+ );
 4508+ }
 4509+
 4510+ return formatCode(
 4511+ "var ${savedPosVar} = pos;",
 4512+ "${code}",
 4513+ {
 4514+ code: code,
 4515+ savedPosVar: savedPosVar
 4516+ }
 4517+ );
 4518+ },
 4519+
 4520+ labeled: function(node, resultVar) {
 4521+ return emit(node.expression, resultVar);
 4522+ },
 4523+
 4524+ simple_and: function(node, resultVar) {
 4525+ var savedPosVar = UID.next("savedPos");
 4526+ var savedReportMatchFailuresVar = UID.next("savedReportMatchFailuresVar");
 4527+ var expressionResultVar = UID.next("result");
 4528+
 4529+ return formatCode(
 4530+ "var ${savedPosVar} = pos;",
 4531+ "var ${savedReportMatchFailuresVar} = reportMatchFailures;",
 4532+ "reportMatchFailures = false;",
 4533+ "${expressionCode}",
 4534+ "reportMatchFailures = ${savedReportMatchFailuresVar};",
 4535+ "if (${expressionResultVar} !== null) {",
 4536+ " var ${resultVar} = '';",
 4537+ " pos = ${savedPosVar};",
 4538+ "} else {",
 4539+ " var ${resultVar} = null;",
 4540+ "}",
 4541+ {
 4542+ expressionCode: emit(node.expression, expressionResultVar),
 4543+ expressionResultVar: expressionResultVar,
 4544+ savedPosVar: savedPosVar,
 4545+ savedReportMatchFailuresVar: savedReportMatchFailuresVar,
 4546+ resultVar: resultVar
 4547+ }
 4548+ );
 4549+ },
 4550+
 4551+ simple_not: function(node, resultVar) {
 4552+ var savedPosVar = UID.next("savedPos");
 4553+ var savedReportMatchFailuresVar = UID.next("savedReportMatchFailuresVar");
 4554+ var expressionResultVar = UID.next("result");
 4555+
 4556+ return formatCode(
 4557+ "var ${savedPosVar} = pos;",
 4558+ "var ${savedReportMatchFailuresVar} = reportMatchFailures;",
 4559+ "reportMatchFailures = false;",
 4560+ "${expressionCode}",
 4561+ "reportMatchFailures = ${savedReportMatchFailuresVar};",
 4562+ "if (${expressionResultVar} === null) {",
 4563+ " var ${resultVar} = '';",
 4564+ "} else {",
 4565+ " var ${resultVar} = null;",
 4566+ " pos = ${savedPosVar};",
 4567+ "}",
 4568+ {
 4569+ expressionCode: emit(node.expression, expressionResultVar),
 4570+ expressionResultVar: expressionResultVar,
 4571+ savedPosVar: savedPosVar,
 4572+ savedReportMatchFailuresVar: savedReportMatchFailuresVar,
 4573+ resultVar: resultVar
 4574+ }
 4575+ );
 4576+ },
 4577+
 4578+ semantic_and: function(node, resultVar) {
 4579+ return formatCode(
 4580+ "var ${resultVar} = (function() {${actionCode}})() ? '' : null;",
 4581+ {
 4582+ actionCode: node.code,
 4583+ resultVar: resultVar
 4584+ }
 4585+ );
 4586+ },
 4587+
 4588+ semantic_not: function(node, resultVar) {
 4589+ return formatCode(
 4590+ "var ${resultVar} = (function() {${actionCode}})() ? null : '';",
 4591+ {
 4592+ actionCode: node.code,
 4593+ resultVar: resultVar
 4594+ }
 4595+ );
 4596+ },
 4597+
 4598+ optional: function(node, resultVar) {
 4599+ var expressionResultVar = UID.next("result");
 4600+
 4601+ return formatCode(
 4602+ "${expressionCode}",
 4603+ "var ${resultVar} = ${expressionResultVar} !== null ? ${expressionResultVar} : '';",
 4604+ {
 4605+ expressionCode: emit(node.expression, expressionResultVar),
 4606+ expressionResultVar: expressionResultVar,
 4607+ resultVar: resultVar
 4608+ }
 4609+ );
 4610+ },
 4611+
 4612+ zero_or_more: function(node, resultVar) {
 4613+ var expressionResultVar = UID.next("result");
 4614+
 4615+ return formatCode(
 4616+ "var ${resultVar} = [];",
 4617+ "${expressionCode}",
 4618+ "while (${expressionResultVar} !== null) {",
 4619+ " ${resultVar}.push(${expressionResultVar});",
 4620+ " ${expressionCode}",
 4621+ "}",
 4622+ {
 4623+ expressionCode: emit(node.expression, expressionResultVar),
 4624+ expressionResultVar: expressionResultVar,
 4625+ resultVar: resultVar
 4626+ }
 4627+ );
 4628+ },
 4629+
 4630+ one_or_more: function(node, resultVar) {
 4631+ var expressionResultVar = UID.next("result");
 4632+
 4633+ return formatCode(
 4634+ "${expressionCode}",
 4635+ "if (${expressionResultVar} !== null) {",
 4636+ " var ${resultVar} = [];",
 4637+ " while (${expressionResultVar} !== null) {",
 4638+ " ${resultVar}.push(${expressionResultVar});",
 4639+ " ${expressionCode}",
 4640+ " }",
 4641+ "} else {",
 4642+ " var ${resultVar} = null;",
 4643+ "}",
 4644+ {
 4645+ expressionCode: emit(node.expression, expressionResultVar),
 4646+ expressionResultVar: expressionResultVar,
 4647+ resultVar: resultVar
 4648+ }
 4649+ );
 4650+ },
 4651+
 4652+ action: function(node, resultVar) {
 4653+ /*
 4654+ * In case of sequences, we splat their elements into function arguments
 4655+ * one by one. Example:
 4656+ *
 4657+ * start: a:"a" b:"b" c:"c" { alert(arguments.length) } // => 3
 4658+ *
 4659+ * This behavior is reflected in this function.
 4660+ */
 4661+
 4662+ var expressionResultVar = UID.next("result");
 4663+
 4664+ if (node.expression.type === "sequence") {
 4665+ var formalParams = [];
 4666+ var actualParams = [];
 4667+
 4668+ var elements = node.expression.elements;
 4669+ var elementsLength = elements.length;
 4670+ for (var i = 0; i < elementsLength; i++) {
 4671+ if (elements[i].type === "labeled") {
 4672+ formalParams.push(elements[i].label);
 4673+ actualParams.push(expressionResultVar + "[" + i + "]");
 4674+ }
 4675+ }
 4676+ } else if (node.expression.type === "labeled") {
 4677+ var formalParams = [node.expression.label];
 4678+ var actualParams = [expressionResultVar];
 4679+ } else {
 4680+ var formalParams = [];
 4681+ var actualParams = [];
 4682+ }
 4683+
 4684+ return formatCode(
 4685+ "${expressionCode}",
 4686+ "var ${resultVar} = ${expressionResultVar} !== null",
 4687+ " ? (function(${formalParams}) {${actionCode}})(${actualParams})",
 4688+ " : null;",
 4689+ {
 4690+ expressionCode: emit(node.expression, expressionResultVar),
 4691+ expressionResultVar: expressionResultVar,
 4692+ actionCode: node.code,
 4693+ formalParams: formalParams.join(", "),
 4694+ actualParams: actualParams.join(", "),
 4695+ resultVar: resultVar
 4696+ }
 4697+ );
 4698+ },
 4699+
 4700+ rule_ref: function(node, resultVar) {
 4701+ return formatCode(
 4702+ "var ${resultVar} = ${ruleMethod}();",
 4703+ {
 4704+ ruleMethod: "parse_" + node.name,
 4705+ resultVar: resultVar
 4706+ }
 4707+ );
 4708+ },
 4709+
 4710+ literal: function(node, resultVar) {
 4711+ return formatCode(
 4712+ "if (input.substr(pos, ${length}) === ${value|string}) {",
 4713+ " var ${resultVar} = ${value|string};",
 4714+ " pos += ${length};",
 4715+ "} else {",
 4716+ " var ${resultVar} = null;",
 4717+ " if (reportMatchFailures) {",
 4718+ " matchFailed(${valueQuoted|string});",
 4719+ " }",
 4720+ "}",
 4721+ {
 4722+ value: node.value,
 4723+ valueQuoted: quote(node.value),
 4724+ length: node.value.length,
 4725+ resultVar: resultVar
 4726+ }
 4727+ );
 4728+ },
 4729+
 4730+ any: function(node, resultVar) {
 4731+ return formatCode(
 4732+ "if (input.length > pos) {",
 4733+ " var ${resultVar} = input.charAt(pos);",
 4734+ " pos++;",
 4735+ "} else {",
 4736+ " var ${resultVar} = null;",
 4737+ " if (reportMatchFailures) {",
 4738+ " matchFailed('any character');",
 4739+ " }",
 4740+ "}",
 4741+ { resultVar: resultVar }
 4742+ );
 4743+ },
 4744+
 4745+ "class": function(node, resultVar) {
 4746+ if (node.parts.length > 0) {
 4747+ var regexp = "/^["
 4748+ + (node.inverted ? "^" : "")
 4749+ + map(node.parts, function(part) {
 4750+ return part instanceof Array
 4751+ ? quoteForRegexpClass(part[0])
 4752+ + "-"
 4753+ + quoteForRegexpClass(part[1])
 4754+ : quoteForRegexpClass(part);
 4755+ }).join("")
 4756+ + "]/";
 4757+ } else {
 4758+ /*
 4759+ * Stupid IE considers regexps /[]/ and /[^]/ syntactically invalid, so
 4760+ * we translate them into euqivalents it can handle.
 4761+ */
 4762+ var regexp = node.inverted ? "/^[\\S\\s]/" : "/^(?!)/";
 4763+ }
 4764+
 4765+ return formatCode(
 4766+ "if (input.substr(pos).match(${regexp}) !== null) {",
 4767+ " var ${resultVar} = input.charAt(pos);",
 4768+ " pos++;",
 4769+ "} else {",
 4770+ " var ${resultVar} = null;",
 4771+ " if (reportMatchFailures) {",
 4772+ " matchFailed(${rawText|string});",
 4773+ " }",
 4774+ "}",
 4775+ {
 4776+ regexp: regexp,
 4777+ rawText: node.rawText,
 4778+ resultVar: resultVar
 4779+ }
 4780+ );
 4781+ }
 4782+ });
 4783+
 4784+ return emit(ast);
 4785+};
 4786+
 4787+if (typeof module === "object") {
 4788+ module.exports = PEG;
 4789+} else if (typeof window === "object") {
 4790+ window.PEG = PEG;
 4791+} else {
 4792+ throw new Error("Can't export PEG library (no \"module\" nor \"window\" object detected).");
 4793+}
 4794+
 4795+})();
Property changes on: trunk/extensions/ParserPlayground/modules/lib.pegjs.js
___________________________________________________________________
Added: svn:eol-style
14796 + native
Index: trunk/extensions/ParserPlayground/modules/ext.parserPlayground.hashMap.js
@@ -0,0 +1,53 @@
 2+/**
 3+ * Very primitive hashmap class that allows using objects as keys;
 4+ * JSON flattening of the key object is used as a hash code, so only
 5+ * suitable for objects that will be immutable for now.
 6+ *
 7+ * Actual final comparison is done using object identity, but the
 8+ * bucket match is from the JSON, so don't mess around!
 9+ *
 10+ * Used to map parse tree nodes to output nodes for the inspector mode.
 11+ */
 12+function HashMap() {
 13+ this.keyBuckets = {};
 14+ this.valBuckets = {};
 15+}
 16+
 17+/**
 18+ * @param {object} keyObj
 19+ * @return {object} original object, or null if no match found.
 20+ */
 21+HashMap.prototype.get = function(keyObj) {
 22+ var key = this.hash(keyObj);
 23+ if (typeof this.keyBuckets[key] !== 'undefined') {
 24+ var keys = this.keyBuckets[key],
 25+ max = keys.length;
 26+ for (var i = 0; i < max; i++) {
 27+ if (keyObj === keys[i]) {
 28+ return this.valBuckets[key][i];
 29+ }
 30+ }
 31+ }
 32+ return null;
 33+};
 34+
 35+/**
 36+ * @param {object} keyObj
 37+ * @param {object} val
 38+ */
 39+HashMap.prototype.put = function(keyObj, val) {
 40+ var key = this.hash(keyObj);
 41+ if (typeof this.keyBuckets[key] === 'undefined') {
 42+ this.keyBuckets[key] = [];
 43+ this.valBuckets[key] = [];
 44+ }
 45+ this.keyBuckets[key].push(keyObj);
 46+ this.valBuckets[key].push(val);
 47+};
 48+
 49+/**
 50+ * This will do for us for now. :)
 51+ */
 52+HashMap.prototype.hash = function(keyObj) {
 53+ return JSON.stringify(keyObj).substr(0, 40);
 54+};
Property changes on: trunk/extensions/ParserPlayground/modules/ext.parserPlayground.hashMap.js
___________________________________________________________________
Added: svn:eol-style
155 + native
Index: trunk/extensions/ParserPlayground/modules/ext.parserPlayground.js
@@ -0,0 +1,347 @@
 2+/**
 3+ * MediaWiki:Gadget-ParserPopups.js
 4+ * Brion Vibber <brion @ pobox.com>
 5+ * 2011-05-02
 6+ *
 7+ * Initial steps on some experiments to flip between various parsing methods to
 8+ * compare source, parse trees, and outcomes.
 9+ *
 10+ * Adds a fold-out section in the editor (using enhanced toolbar) to swap view of:
 11+ * - Source (your regular editable text)
 12+ * - MediaWiki parser (parsed page as full HTML)
 13+ * - Preprocessor tree (tree view of XML preprocessor tree; shows limited pre-parsing breakdown)
 14+ * - FakeParser (a very primitive parser class in this gadget)
 15+ * - FakeParser's parse tree
 16+ * - FakeParser's output and parse tree side-by-side.
 17+ *
 18+ * The parsed views update to match the current editor state when you bump over to them.
 19+ * In side-by-side view, matching items are highlighted on the two sides, and clicking
 20+ * will scroll the related side into view if needed.
 21+ */
 22+(function( $ ) {
 23+
 24+function htmlEscape(str) {
 25+ return mw.html.escape( str );
 26+}
 27+
 28+/**
 29+ * Render an XML tree into this thingy.
 30+ * @param {DOMNode} node
 31+ * @param {jQuery} dest a list object!
 32+ * @param {HashMap} inspectorMap
 33+ */
 34+function renderXmlTree(node, dest, inspectorMap) {
 35+ if (node.nodeType == Node.ELEMENT_NODE) {
 36+ var base = '<span style="color:#808">' + htmlEscape(node.nodeName) + '</span>',
 37+ str = '&lt;' + base,
 38+ closer;
 39+ $.each(node.attributes, function(i, attr) {
 40+ str += ' ' + htmlEscape(attr.nodeName) + '=<span style="color:#008">"' + htmlEscape(htmlEscape(attr.nodeValue)) + '"</span>';
 41+ });
 42+ if (node.childNodes.length == 0) {
 43+ str += ' /&gt;';
 44+ dest.append('<li>' + str + '</li>');
 45+ } else {
 46+ str += '&gt;';
 47+ closer = '&lt;/' + base + '&gt;';
 48+ var chunk = $('<li>' +
 49+ '<div class="mw-pp-node">' + str + '</div>' +
 50+ '<ul></ul>' +
 51+ '<div class="mw-pp-node">' + closer + '</div>' +
 52+ '</li>');
 53+ var sublist = chunk.find('ul');
 54+ dest.append(chunk);
 55+ $.each(node.childNodes, function(i, child) {
 56+ renderXmlTree(child, sublist);
 57+ });
 58+ }
 59+ } else if (node.nodeType == Node.TEXT_NODE) {
 60+ dest.append($('<li style="white-space: pre-wrap; font-family: monospace"></li>').text(node.textContent));
 61+ }
 62+}
 63+
 64+/**
 65+ * Render a JSON tree into this thingy.
 66+ * @param {mixed} node
 67+ * @param {jQuery} dest a list object!
 68+ * @param {HashMap} inspectorMap
 69+ */
 70+function renderJsonTree(node, dest, inspectorMap) {
 71+ var type = (typeof node);
 72+ var chunk, item, sublist;
 73+ if (type == 'object' && node === null) {
 74+ dest.append('null');
 75+ } else if (type == 'object' && node instanceof Array) {
 76+ chunk = $('<div>' +
 77+ '<span class="mw-pp-node">[</span>' +
 78+ '<ul></ul>' +
 79+ '<span class="mw-pp-node">]</span>' +
 80+ '</div>');
 81+ sublist = chunk.find('ul');
 82+ $.each(node, function(i, val) {
 83+ item = $('<li></li>');
 84+ renderJsonTree(val, item, inspectorMap);
 85+ sublist.append(item);
 86+ });
 87+ dest.append(chunk);
 88+ } else if (type == 'object') {
 89+ chunk = $('<div class="parseNode">' +
 90+ '<span class="mw-pp-node">{</span>' +
 91+ '<ul></ul>' +
 92+ '<span class="mw-pp-node">}</span>' +
 93+ '</div>');
 94+ chunk.data('parseNode', node); // assign the node for the tree inspector
 95+ if (inspectorMap) {
 96+ // save reverse lookup for the inspector
 97+ inspectorMap.put(node, chunk[0]);
 98+ }
 99+ sublist = chunk.find('ul'); // hack
 100+ $.each(node, function(key, val) {
 101+ var item = $('<li><span style="color:#808">' + htmlEscape('' + key) + '</span>:&nbsp;</li>');
 102+ renderJsonTree(val, item, inspectorMap);
 103+ sublist.append(item);
 104+ });
 105+ dest.append(chunk);
 106+ } else if (type == 'string') {
 107+ dest.append(htmlEscape(JSON.stringify(node))); // easy way to escape :)
 108+ } else {
 109+ dest.append(htmlEscape('' + node));
 110+ }
 111+}
 112+
 113+/**
 114+ * Render a JSON or XML tree into this thingy.
 115+ * @param {mixed} node
 116+ * @param {jQuery} dest a list object!
 117+ * @param {HashMap} inspectorMap
 118+ */
 119+function renderTree(node, dest, inspectorMap) {
 120+ var render;
 121+ if (node instanceof Node) {
 122+ render = renderXmlTree;
 123+ } else {
 124+ render = renderJsonTree;
 125+ }
 126+ render(node, dest, inspectorMap);
 127+}
 128+
 129+
 130+var onResize = null;
 131+$(window).resize(function() {
 132+ if (onResize) {
 133+ onResize();
 134+ }
 135+});
 136+$('.mw-pp-node').live('click', function() {
 137+ var ul = $(this.parentNode).find('ul:first');
 138+ if (ul.is(":hidden")) {
 139+ ul.slideDown();
 140+ } else {
 141+ ul.slideUp();
 142+ }
 143+});
 144+
 145+var makeMagicBox = function(inside) {
 146+ $('#mw-parser-popup').remove();
 147+ // line-height is needed to compensate for oddity in WikiEditor extension, which zeroes the line-height on a parent container
 148+ var box = $('#wpTextbox1');
 149+ var target = $('<div id="mw-parser-popup" style="position: relative; z-index: 9999; overflow: auto; background: white"><div class="editor" style="line-height: 1.5em; top: 0px; left: 0px; right: 0px; bottom: 0px; border: 1px solid gray">' + inside + '</div></div>').insertAfter(box);
 150+ $('#wpTextbox1').css('display', 'none');
 151+
 152+ onResize = function() {
 153+ target.width(box.width())
 154+ .height(box.height());
 155+ };
 156+ onResize();
 157+ return target;
 158+};
 159+
 160+/**
 161+ * Create two scrollable columns for an 'inspector' display.
 162+ * @param {jQuery} dest -- jquery obj to receive the target
 163+ * @return {jQuery}
 164+ */
 165+var makeInspectorColumns = function(dest) {
 166+ var h = $('#wpTextbox1').height(); // hack
 167+ var target = $(
 168+ '<table style="width: 100%; height: ' + h + 'px">' +
 169+ '<tr>' +
 170+ '<td width="50%"><div class="left" style="overflow:auto; ' +
 171+ 'height: ' + h + 'px"></div></td>' +
 172+ '<td width="50%"><div class="right" style="overflow:auto; ' +
 173+ 'height: ' + h + 'px"></div></td>' +
 174+ '</tr>' +
 175+ '</table>').appendTo(dest);
 176+ return target;
 177+};
 178+
 179+/**
 180+ * Set up 'inspector' events to highlight elements with matching parseNode data properties
 181+ * between the given two sections.
 182+ *
 183+ * @param {jQuery} left
 184+ * @param {jQUery} right
 185+ */
 186+var setupInspector = function(left, right, leftMap, rightMap) {
 187+ var makeMagic = function(a, b, inspectorMap) {
 188+ var match = function(aNode, callback) {
 189+ var treeNode = $(aNode).data('parseNode');
 190+ var bNode = treeNode && inspectorMap.get(treeNode);
 191+ callback(aNode, bNode);
 192+ };
 193+ a.delegate('.parseNode', 'mouseenter', function(event) {
 194+ match(this, function(node, other) {
 195+ $(node).addClass('parseNodeHighlight');
 196+ $(other).addClass('parseNodeHighlight');
 197+ });
 198+ }).delegate('.parseNode', 'mouseleave', function(event) {
 199+ match(this, function(node, other) {
 200+ $(node).removeClass('parseNodeHighlight');
 201+ $(other).removeClass('parseNodeHighlight');
 202+ });
 203+ }).delegate('.parseNode', 'click', function(event) {
 204+ match(this, function(node, other) {
 205+ if (other) {
 206+ // try to scroll the other into view. how... feasible is this? :DD
 207+ var visibleStart = b.scrollTop();
 208+ var visibleEnd = visibleStart + b.height();
 209+ var otherStart = visibleStart + $(other).position().top;
 210+ var otherEnd = otherStart + $(other).height();
 211+ if (otherStart > visibleEnd) {
 212+ b.scrollTop(otherStart);
 213+ } else if (otherEnd < visibleStart) {
 214+ b.scrollTop(otherStart);
 215+ }
 216+ event.preventDefault();
 217+ return false;
 218+ }
 219+ });
 220+ });
 221+ };
 222+ makeMagic(left, right, rightMap);
 223+ makeMagic(right, left, leftMap);
 224+};
 225+
 226+var addParserModes = function(modes, parserClass, className, detail) {
 227+ detail = detail || '';
 228+ modes[className] = {
 229+ label: className,
 230+ desc: '<p>Showing the page rendered with ' + className + '.</p>' + detail,
 231+ render: function(src, dest) {
 232+ var parser = new parserClass();
 233+ parser.parseToTree(src, function(tree, err) {
 234+ parser.treeToHtml(tree, function(node, err) {
 235+ dest.append(node);
 236+ });
 237+ });
 238+ }
 239+ };
 240+ modes[className + '-tree'] = {
 241+ label: className + ' tree',
 242+ desc: '<p>Showing the page broken down to parse tree with ' + className + '.</p>' + detail,
 243+ render: function(src, dest) {
 244+ var parser = new parserClass();
 245+ parser.parseToTree(src, function(tree, err) {
 246+ var target = $('<ul><li></li></ul>').appendTo(dest);
 247+ renderTree(tree, target.find('li'));
 248+ });
 249+ }
 250+ };
 251+ modes[className + '-roundtrip'] = {
 252+ label: className + ' round-trip',
 253+ desc: '<p>Showing the page as parsed, then returned to source via ' + className + '.</p>' + detail,
 254+ render: function(src, dest) {
 255+ var parser = new parserClass();
 256+ parser.parseToTree(src, function(tree, err) {
 257+ parser.treeToSource(tree, function(src2, err) {
 258+ var target = $('<div style="white-space: pre-wrap; font-family: monospace">').appendTo(dest);
 259+ target.html(diffString(src, src2));
 260+ });
 261+ });
 262+ }
 263+ };
 264+ modes[className + '-inspect'] = {
 265+ label: className + ' inspect',
 266+ desc: '<p>Shows ' + className + '\'s HTML output and parse tree side-by-side.</p>' + detail,
 267+ render: function(src, dest) {
 268+ var parser = new parserClass();
 269+ var treeMap = new HashMap(), renderMap = new HashMap();
 270+ parser.parseToTree(src, function(tree, err) {
 271+ var target = makeInspectorColumns(dest);
 272+ var left = target.find('.left'), right = target.find('.right');
 273+ renderTree(tree, left, treeMap);
 274+ parser.treeToHtml(tree, function(node, err) {
 275+ right.append(node);
 276+ setupInspector(left, right, treeMap, renderMap);
 277+ }, renderMap);
 278+ });
 279+ }
 280+ };
 281+};
 282+
 283+$(document).ready( function() {
 284+ /* Start trying to add items... */
 285+ var editor = $('#wpTextbox1');
 286+ if (editor.length > 0 && typeof $.fn.wikiEditor === 'function') {
 287+ //$('#wpTextbox1').bind('wikiEditor-toolbar-buildSection-main', function() {
 288+ var modes = {
 289+ 'source': {
 290+ label: 'Source',
 291+ desc: 'Showing the page\'s original wikitext source code, as you are used to editing it.',
 292+ render: false
 293+ }
 294+ };
 295+ addParserModes(modes, MediaWikiParser, 'MediaWikiParser');
 296+ addParserModes(modes, FakeParser, 'FakeParser');
 297+ addParserModes(modes, PegParser, 'PegParser', '<p>Peg-based parser plus FakeParser\'s output. <a href="http://pegjs.majda.cz/documentation">pegjs documentation</a>; edit and reselect to reparse with updated parser</p>');
 298+
 299+ window.setTimeout(function() {
 300+ // Great, now let's hook the booklet buttons... (explicit callbacks would be better)
 301+ var hook = function(key, callback) {
 302+ // using live since they haven't been created yet...
 303+ // 'mouseup' as a hack since the upstream click handler cancels other event handlers
 304+ $('#wikiEditor-ui-toolbar .sections .section-parser .index div[rel=' + key + ']').live('mouseup', callback);
 305+ };
 306+ var pages = {};
 307+ $.each(modes, function(name, mode) {
 308+ pages[name] = {
 309+ 'layout': 'table',
 310+ 'label': mode.label,
 311+ 'rows': [
 312+ {
 313+ 'desc': { 'html': mode.desc }
 314+ }
 315+ ]
 316+ };
 317+ var render = mode.render;
 318+ hook(name, function() {
 319+ $('#pegparser-source').hide(); // it'll reshow; others won't need it
 320+ if (mode.render) {
 321+ var target = makeMagicBox('');
 322+ var src = $('#wpTextbox1').val();
 323+ var dest = target.find('div');
 324+ render(src, dest);
 325+ } else {
 326+ $('#mw-parser-popup').remove();
 327+ onResize = null;
 328+ $('#wpTextbox1').css('display', 'block');
 329+ }
 330+ });
 331+ });
 332+ editor.wikiEditor( 'addToToolbar', {
 333+ 'sections': {
 334+ 'parser': {
 335+ 'label': 'Parser',
 336+ 'type': 'booklet',
 337+ 'pages': pages
 338+ }
 339+ }
 340+ } );
 341+
 342+ }, 500 );
 343+ } else {
 344+ mw.log('No wiki editor');
 345+ }
 346+});
 347+
 348+})(jQuery);
Property changes on: trunk/extensions/ParserPlayground/modules/ext.parserPlayground.js
___________________________________________________________________
Added: svn:eol-style
1349 + native
Index: trunk/extensions/ParserPlayground/modules/ext.parserPlayground.fakeParser.js
@@ -0,0 +1,381 @@
 2+/**
 3+ * @param {ParserContext} context
 4+ */
 5+function FakeParser(context) {
 6+ // whee
 7+ this.context = context || {};
 8+}
 9+
 10+/**
 11+ * @param {string} text
 12+ * @param {function(tree, error)} callback
 13+ */
 14+FakeParser.prototype.parseToTree = function(text, callback) {
 15+ // quick and crappy :D
 16+ var lines = text.split("\n");
 17+ var blocks = [];
 18+ var matches;
 19+ /**
 20+ * Subparse of inline links within a paragraph etc.
 21+ * @param {string} line
 22+ * @return {object[]} list of content subblocks
 23+ */
 24+ var linksParse = function(line) {
 25+ var bits = line.split('[['),
 26+ parts = [];
 27+ if (bits[0] != '') {
 28+ parts.push({
 29+ type: 'text',
 30+ text: bits[0]
 31+ });
 32+ }
 33+ for (var i = 1; i < bits.length; i++) {
 34+ var bit = bits[i];
 35+ var bracketPos = bit.indexOf(']]');
 36+ if (bracketPos === -1) {
 37+ // not a link oh noooooo
 38+ parts.push({
 39+ type: 'text',
 40+ text: '[[' + bit
 41+ });
 42+ } else {
 43+ var link = bit.substr(0, bracketPos);
 44+ var tail = bit.substr(bracketPos + 2);
 45+ var linkbits = link.split('|');
 46+ if (linkbits.length == 1) {
 47+ parts.push({
 48+ type: 'link',
 49+ target: link
 50+ });
 51+ } else {
 52+ parts.push({
 53+ type: 'link',
 54+ target: linkbits[0],
 55+ text: linkbits.slice(1).join('|') // @fixme multiples for images etc
 56+ });
 57+ }
 58+ if (tail !== '') {
 59+ parts.push({
 60+ type: 'text',
 61+ text: tail
 62+ });
 63+ }
 64+ }
 65+ }
 66+ return parts;
 67+ };
 68+ /**
 69+ * Subparse of all inline stuff within a paragraph etc.
 70+ * @param {string} line
 71+ * @return {object[]} list of content subblocks
 72+ */
 73+ var inlineParse = function(line) {
 74+ var parts = [];
 75+ var bits = line.split('<ref');
 76+ var re = /^([^>]*)>(.*)<\/ref\s*>(.*)/;
 77+ var re2 = /^([^>]*)\/>(.*)/;
 78+ if (bits[0] != '') {
 79+ // text before...
 80+ $.merge(parts, linksParse(bits[0]));
 81+ }
 82+ $.each(bits.slice(1), function(i, bit) {
 83+ var matches;
 84+ var after;
 85+ if ((matches = re.exec(bit)) != null) {
 86+ var params = matches[1], text = matches[2];
 87+ after = matches[3];
 88+ parts.push({
 89+ type: 'ext',
 90+ name: 'ref',
 91+ params: params,
 92+ content: (text == '') ? [] : linksParse(text)
 93+ });
 94+ } else if ((matches = re2.exec(bit)) != null) {
 95+ var params = matches[1];
 96+ after = matches[2];
 97+ parts.push({
 98+ type: 'ext',
 99+ name: 'ref',
 100+ params: params
 101+ });
 102+ } else {
 103+ after = '<ref' + bit;
 104+ }
 105+ if (after != '') {
 106+ $.merge(parts, linksParse(after));
 107+ }
 108+ });
 109+ return parts;
 110+ };
 111+ $.each(lines, function(i, line) {
 112+ if (line == '') {
 113+ blocks.push({
 114+ type: 'break'
 115+ });
 116+ } else if (matches = /^(={1,6})(.*)\1$/.exec(line)) {
 117+ blocks.push({
 118+ type: 'h',
 119+ level: matches[1].length,
 120+ text: matches[2]
 121+ });
 122+ } else {
 123+ var parts = inlineParse(line);
 124+ blocks.push({
 125+ type: 'para',
 126+ content: parts
 127+ });
 128+ }
 129+ });
 130+ var tree = {
 131+ type: 'page',
 132+ content: blocks
 133+ };
 134+ callback(tree, null);
 135+};
 136+
 137+/**
 138+ * @param {object} tree
 139+ * @param {function(tree, error)} callback
 140+ */
 141+FakeParser.prototype.expandTree = function(tree, callback) {
 142+ // no-op!
 143+ callback(tree, null);
 144+};
 145+
 146+/**
 147+ * @param {object} tree
 148+ * @param {function(domnode, error)} callback
 149+ * @param {HashMap} inspectorMap
 150+ */
 151+FakeParser.prototype.treeToHtml = function(tree, callback, inspectorMap) {
 152+ var self = this;
 153+ var subParseArray = function(listOfTrees, node) {
 154+ $.each(listOfTrees, function(i, subtree) {
 155+ self.treeToHtml(subtree, function(subnode, err) {
 156+ if (subnode) {
 157+ node.append(subnode);
 158+ }
 159+ }, inspectorMap);
 160+ });
 161+ };
 162+ var node;
 163+ switch (tree.type) {
 164+ case 'page':
 165+ // A sequence of block-level elements...
 166+ var page = $('<div class="parseNode"></div>');
 167+ subParseArray(tree.content, page);
 168+ if (self.context.refs) {
 169+ // We're at the end; drop all the remaining refs!
 170+ subParseArray([{
 171+ type: 'ext',
 172+ name: 'references'
 173+ }], page);
 174+ }
 175+ node = page[0];
 176+ break;
 177+ case 'para':
 178+ // A single-line paragraph.
 179+ var para = $('<p class="parseNode"></p>');
 180+ subParseArray(tree.content, para);
 181+ node = para[0];
 182+ break;
 183+ case 'break':
 184+ // Just a stub in the parse tree.
 185+ break;
 186+ case 'text':
 187+ // hack hack
 188+ node = document.createTextNode(tree.text);
 189+ break;
 190+ case 'link':
 191+ var link = $('<a class="parseNode"></a>');
 192+ link.text(tree.text || tree.target);
 193+ link.attr('href', '/wiki/' + tree.target); // hack
 194+ node = link[0];
 195+ break;
 196+ case 'extlink':
 197+ var link = $('<a class="parseNode"></a>');
 198+ link.text(tree.text || tree.target); // fixme? #d links, freelinks etc
 199+ link.attr('href', tree.target); // hack: validate etc
 200+ node = link[0];
 201+ break;
 202+ case 'h':
 203+ var h = $('<h' + tree.level + ' class="parseNode"></h' + tree.level + '>').text(tree.text);
 204+ node = h[0];
 205+ break;
 206+ case 'i':
 207+ var h = $('<i class="parseNode"></i>').text(tree.text); // hack -- use contents[]
 208+ node = h[0];
 209+ break;
 210+ case 'template':
 211+ var t = $('<span class="parseNode template"></span>').text('{{' + tree.target);
 212+ if ('params' in tree) {
 213+ $.each(tree.params, function(i, param) {
 214+ var str = param.contents;
 215+ if ('name' in param) {
 216+ str = param.name + '=' + str;
 217+ }
 218+ var p = $('<span></span>').text('|' + str);
 219+ t.append(p);
 220+ });
 221+ }
 222+ t.append('}}');
 223+ node = t[0];
 224+ break;
 225+ case 'ext':
 226+ if (tree.name == 'ref') {
 227+ // Save the reference for later!
 228+ // @fixme names etc?
 229+ if (self.context.refs === undefined) {
 230+ self.context.refs = [];
 231+ }
 232+ self.context.refs.push(tree);
 233+ var refNum = self.context.refs.length;
 234+ var ref = $('<span class="ref parseNode">[</span>');
 235+ $('<a></a>')
 236+ .text(refNum + '')
 237+ .attr('src', '#ref-' + refNum)
 238+ .appendTo(ref);
 239+ ref.append(']');
 240+ node = ref[0];
 241+ } else if (tree.name == 'references') {
 242+ // Force inline expansion of references with a given group
 243+ // @fixme support multiple groups etc
 244+ var references = $('<ol class="references parseNode"></ol>');
 245+ var oldRefs = self.context.refs;
 246+ self.context.refs = [];
 247+ $.each(oldRefs, function(i, subtree) {
 248+ var ref = $('<li class="ref parseNode" id="ref-' + i + '"></li>');
 249+ if ('content' in subtree) {
 250+ subParseArray(subtree.content, ref);
 251+ }
 252+ references.append(ref);
 253+ });
 254+ node = references[0];
 255+ } else if (tree.name == 'cite') {
 256+ // Kinda like a ref but inline.
 257+ // @fixme validate and output the tag parameters
 258+ var cite = $('<span class="cite parseNode"></span>');
 259+ if ('content' in tree) {
 260+ subParseArray(tree.content, cite);
 261+ }
 262+ node = cite[0];
 263+ } else {
 264+ // @fixme unrecognized exts should output as text + rendered contents?
 265+ callback(null, 'Unrecognized extension in parse tree');
 266+ return;
 267+ }
 268+ break;
 269+ default:
 270+ callback(null, 'Unrecognized parse tree node');
 271+ return;
 272+ }
 273+ if (node) {
 274+ if (node.nodeType == 1) {
 275+ $(node).data('parseNode', tree); // assign the node for the tree inspector
 276+ if (inspectorMap) {
 277+ inspectorMap.put(tree, node); // store for reverse lookup
 278+ }
 279+ }
 280+ callback(node);
 281+ } else {
 282+ callback(null); // hmmmm
 283+ }
 284+};
 285+
 286+/**
 287+ * Collapse a parse tree back to source, if possible.
 288+ * Ideally should exactly match the original source;
 289+ * at minimum the resulting source should parse into
 290+ * a tree that's identical to the current one.
 291+ *
 292+ * @param {object} tree
 293+ * @param {function(text, error)} callback
 294+ */
 295+FakeParser.prototype.treeToSource = function(tree, callback) {
 296+ var self = this;
 297+ var subParseArray = function(listOfTrees) {
 298+ var str = '';
 299+ $.each(listOfTrees, function(i, subtree) {
 300+ self.treeToSource(subtree, function(substr, err) {
 301+ if (substr) {
 302+ str += substr;
 303+ }
 304+ });
 305+ });
 306+ return str;
 307+ };
 308+ var src;
 309+ switch (tree.type) {
 310+ case 'page':
 311+ src = subParseArray(tree.content);
 312+ break;
 313+ case 'para':
 314+ // A single-line paragraph.
 315+ src = subParseArray(tree.content) + '\n';
 316+ break;
 317+ case 'break':
 318+ src = '\n';
 319+ break;
 320+ case 'text':
 321+ // In the real world, there might be escaping.
 322+ src = tree.text;
 323+ break;
 324+ case 'link':
 325+ src = '[[';
 326+ src += tree.target;
 327+ if (tree.text) {
 328+ src += '|';
 329+ src += tree.text;
 330+ }
 331+ src += ']]';
 332+ break;
 333+ case 'h':
 334+ stub = '';
 335+ for (var i = 0; i < tree.level; i++) {
 336+ stub += '=';
 337+ }
 338+ src = stub + tree.text + stub + '\n';
 339+ break;
 340+ case 'ext':
 341+ src = '<' + tree.name;
 342+ if (tree.params) {
 343+ src += ' ' + tree.params;
 344+ }
 345+ if ('content' in tree) {
 346+ src += '>';
 347+ src += subParseArray(tree.content);
 348+ src += '</' + tree.name + '>';
 349+ } else {
 350+ src += '/>';
 351+ }
 352+ break;
 353+ case 'template':
 354+ src = '{{' + tree.target;
 355+ if (tree.params) {
 356+ for (var i = 0; i < tree.params.length; i++) {
 357+ var param = tree.params[i];
 358+ src += '|';
 359+ if ('name' in param) {
 360+ src += param.name + '=';
 361+ }
 362+ src += param.contents;
 363+ }
 364+ }
 365+ src += '}}';
 366+ break;
 367+ case 'i':
 368+ src = "''" + tree.text + "''";
 369+ break;
 370+ case 'extlink':
 371+ src = '[' + tree.target + ' ' + tree.text + ']';
 372+ break;
 373+ default:
 374+ callback(null, 'Unrecognized parse tree node');
 375+ return;
 376+ }
 377+ if (src) {
 378+ callback(src);
 379+ } else {
 380+ callback(null); // hmmmm
 381+ }
 382+};
Property changes on: trunk/extensions/ParserPlayground/modules/ext.parserPlayground.fakeParser.js
___________________________________________________________________
Added: svn:eol-style
1383 + native
Index: trunk/extensions/ParserPlayground/modules/pegParser.pegjs.txt
@@ -0,0 +1,255 @@
 2+/* Produces output more or less compatible with FakeParser; plug it into FP's output and see */
 3+
 4+start
 5+ = e:block* { return {type: 'page', content: e } }
 6+
 7+anything
 8+ = a:[A-Za-z0-9,._ -]+ { return a.join('') } / [^\n]
 9+
 10+space
 11+ = s:[ ]+ { return s.join(''); }
 12+
 13+newline
 14+ = [\n]
 15+
 16+block
 17+ = h
 18+ / br
 19+ / para
 20+
 21+h = h1 / h2 / h3 / h4 / h5 / h6
 22+
 23+h1 = '=' c:heading_text '=' newline {
 24+ return {
 25+ type: 'h',
 26+ level: 1,
 27+ text: c
 28+ }
 29+}
 30+
 31+h2 = '==' c:heading_text '==' newline {
 32+ return {
 33+ type: 'h',
 34+ level: 2,
 35+ text: c
 36+ }
 37+}
 38+
 39+h3 = '===' c:heading_text '===' newline {
 40+ return {
 41+ type: 'h',
 42+ level: 3,
 43+ text: c
 44+ }
 45+}
 46+
 47+h4 = '====' c:heading_text '====' newline {
 48+ return {
 49+ type: 'h',
 50+ level: 4,
 51+ text: c
 52+ }
 53+}
 54+
 55+h5 = '=====' c:heading_text '=====' newline {
 56+ return {
 57+ type: 'h',
 58+ level: 5,
 59+ text: c
 60+ }
 61+}
 62+
 63+h6 = '======' c:heading_text '======' newline {
 64+ return {
 65+ type: 'h',
 66+ level: 6,
 67+ text: c
 68+ }
 69+}
 70+
 71+heading_marker
 72+ = '=' '='*
 73+
 74+heading_text
 75+ = h:( !heading_marker x:(anything) { return x } )* { return h.join(''); }
 76+
 77+br
 78+ = newline { return {type: 'br'} }
 79+
 80+para
 81+ = c:inline newline { return {type: 'para', content: c } }
 82+
 83+inline
 84+ = c:inline_element+ {
 85+ var out = [];
 86+ var text = '';
 87+ for (var i = 0; i < c.length; i++) {
 88+ if (typeof c[i] == 'string') {
 89+ text += c[i];
 90+ } else {
 91+ if (text.length) {
 92+ out.push({
 93+ type: 'text',
 94+ text: text
 95+ });
 96+ text = '';
 97+ }
 98+ out.push(c[i]);
 99+ }
 100+ }
 101+ if (text.length) {
 102+ out.push({
 103+ type: 'text',
 104+ text: text
 105+ });
 106+ }
 107+ return out;
 108+}
 109+
 110+inline_element
 111+ = ref
 112+ / extlink
 113+ / template
 114+ / link
 115+ / italic
 116+ / anything
 117+
 118+inline_text_run
 119+ = c:[^\n]+ { return c.join(''); }
 120+
 121+extlink
 122+ = "[" target:url space text:extlink_text "]" {
 123+ return {
 124+ type: 'extlink',
 125+ target: target,
 126+ text: text
 127+ }
 128+}
 129+
 130+// = "[" target:url text:extlink_text "]" { return { type: 'extlink', target: target, text: text } }
 131+
 132+url
 133+ = proto:"http:" rest:([^ \]]+) { return proto + rest.join(''); }
 134+
 135+extlink_text
 136+ = c:[^\]]+ { return c.join(''); }
 137+
 138+template
 139+ = "{{" target:link_target params:("|" p:template_param { return p })* "}}" {
 140+ var obj = {
 141+ type: 'template',
 142+ target: target
 143+ };
 144+ if (params && params.length) {
 145+ obj.params = params;
 146+ }
 147+ return obj;
 148+}
 149+
 150+template_param
 151+ = name:template_param_name "=" c:template_param_text {
 152+ return {
 153+ name: name,
 154+ contents: c
 155+ };
 156+} / c:template_param_text {
 157+ return {
 158+ contents: c
 159+ };
 160+}
 161+
 162+template_param_name
 163+ = h:( !"}}" x:([^=|]) { return x } )* { return h.join(''); }
 164+
 165+template_param_text
 166+ = h:( !"}}" x:([^|]) { return x } )* { return h.join(''); }
 167+
 168+link
 169+ = "[[" target:link_target text:("|" link_text)* "]]" {
 170+ var obj = {
 171+ type: 'link',
 172+ target: target
 173+ };
 174+ if (text && text.length) {
 175+ obj.text = text[0][1]; // ehhhh
 176+ }
 177+ return obj;
 178+}
 179+
 180+link_target
 181+ = h:( !"]]" x:([^|]) { return x } )* { return h.join(''); }
 182+
 183+link_text
 184+ = h:( !"]]" x:(anything) { return x } )* { return h.join(''); }
 185+
 186+
 187+italic
 188+ = italic_marker c:italic_text italic_marker {
 189+ return {
 190+ type: 'i',
 191+ text: c
 192+ }
 193+}
 194+
 195+italic_marker
 196+ = "''"
 197+
 198+italic_text
 199+ = h:( !italic_marker x:(anything) { return x } )+ { return h.join(''); }
 200+
 201+
 202+ref = ref_full / ref_empty
 203+
 204+ref_full
 205+ = params:ref_start ">" content:ref_content+ close:ref_end {
 206+ return {
 207+ type: 'ext',
 208+ name: 'ref',
 209+ params: params,
 210+ content: content,
 211+ close: close
 212+ }
 213+}
 214+
 215+ref_empty
 216+ = params:ref_start "/>" {
 217+ return {
 218+ type: 'ext',
 219+ name: 'ref',
 220+ params: params
 221+ }
 222+}
 223+
 224+ref_start
 225+ = "<ref" params:ext_param* space* {
 226+ var obj = {};
 227+ for (var i = 0; i < params.length; i++) {
 228+ obj[params[i][0]] = params[i][1];
 229+ }
 230+ return obj;
 231+}
 232+
 233+ref_end
 234+ = all:("</ref" space* ">") {
 235+ return all.join('');
 236+}
 237+
 238+ref_content
 239+ = !ref_end a:inline_element {
 240+ return a;
 241+}
 242+
 243+ext_param
 244+ = space* name:ext_param_name "=" val:ext_param_val {
 245+ return [name, val];
 246+}
 247+
 248+ext_param_name
 249+ = name:[a-zA-Z0-9-]+ {
 250+ return name.join('');
 251+}
 252+
 253+ext_param_val
 254+ = t:[0-9A-Za-z]+ { return t.join('') }
 255+ / "'" t:[^'>]+ "'" { return t.join('') }
 256+ / '"' t:[^">]+ '"' { return t.join('') }
Property changes on: trunk/extensions/ParserPlayground/modules/pegParser.pegjs.txt
___________________________________________________________________
Added: svn:eol-style
1257 + native
Index: trunk/extensions/ParserPlayground/ParserPlayground.hooks.php
@@ -0,0 +1,9 @@
 2+<?php
 3+
 4+class ParserPlaygroundHooks {
 5+ public static function editPageShowEditFormInitial( &$toolbar ) {
 6+ global $wgOut;
 7+ $wgOut->addModules( 'ext.parserPlayground' );
 8+ return true;
 9+ }
 10+}
Property changes on: trunk/extensions/ParserPlayground/ParserPlayground.hooks.php
___________________________________________________________________
Added: svn:eol-style
111 + native
Index: trunk/extensions/ParserPlayground/README
@@ -0,0 +1,7 @@
 2+Parser & editor experiments; framework to integrate them into WikiEditor and
 3+to make available as a gadget.
 4+
 5+These files are under fairly rapid development, so watch out. :)
 6+
 7+-- brion
 8+June 2011

Status & tagging log