From bbc92b36e7c40ff75f3c09c2759aecdd80c7e1f0 Mon Sep 17 00:00:00 2001
From: Jairo de Morais <jdemorais@linkedin.com>
Date: Fri, 18 May 2012 16:25:36 -0300
Subject: [PATCH] rhino compatible

---
 dist/dust-core-0.4.0.js |   10 +-
 dist/dust-full-0.4.0.js | 3072 ++++++++++++++++++---------------------
 lib/compiler.js         |    2 +-
 lib/dust-helpers.js     |    2 +-
 lib/dust.js             |    8 +-
 lib/parser.js           |    2 +-
 src/build.js            |    2 +-
 7 files changed, 1456 insertions(+), 1642 deletions(-)

diff --git a/dist/dust-core-0.4.0.js b/dist/dust-core-0.4.0.js
index dc2f66d2..df9feee5 100644
--- a/dist/dust-core-0.4.0.js
+++ b/dist/dust-core-0.4.0.js
@@ -8,6 +8,12 @@
 
 var dust = {};
 
+function getGlobal(){	
+  return (function(){	
+    return this.dust;	
+      }).call(null);
+}
+
 (function(dust) {
 
 dust.cache = {};
@@ -509,7 +515,7 @@ dust.escapeJs = function(s) {
 
 if (typeof exports !== "undefined") {
   dust.helpers = require("./dust-helpers").helpers;
-  if (typeof process !== "undefined" && typeof window === "undefined") {
+  if (typeof process !== "undefined") {
       require('./server')(dust);
   }
   module.exports = dust;
@@ -564,4 +570,4 @@ var helpers = {
 
 dust.helpers = helpers;
 
-})(typeof exports !== 'undefined' ? exports : window.dust);
\ No newline at end of file
+})(typeof exports !== 'undefined' ? exports : getGlobal());
\ No newline at end of file
diff --git a/dist/dust-full-0.4.0.js b/dist/dust-full-0.4.0.js
index db0f03ba..60a4c7db 100644
--- a/dist/dust-full-0.4.0.js
+++ b/dist/dust-full-0.4.0.js
@@ -8,6 +8,12 @@
 
 var dust = {};
 
+function getGlobal(){	
+  return (function(){	
+    return this.dust;	
+      }).call(null);
+}
+
 (function(dust) {
 
 dust.cache = {};
@@ -509,7 +515,7 @@ dust.escapeJs = function(s) {
 
 if (typeof exports !== "undefined") {
   dust.helpers = require("./dust-helpers").helpers;
-  if (typeof process !== "undefined" && typeof window === "undefined") {
+  if (typeof process !== "undefined") {
       require('./server')(dust);
   }
   module.exports = dust;
@@ -564,7 +570,7 @@ var helpers = {
 
 dust.helpers = helpers;
 
-})(typeof exports !== 'undefined' ? exports : window.dust);(function(dust) {
+})(typeof exports !== 'undefined' ? exports : getGlobal());(function(dust) {
 
 dust.compile = function(source, name) {
   try {
@@ -889,11 +895,38 @@ var escape = (typeof JSON === "undefined")
   ? function(str) { return "\"" + dust.escapeJs(str) + "\"" }
   : JSON.stringify;
 
-})(typeof exports !== 'undefined' ? exports : window.dust);
+})(typeof exports !== 'undefined' ? exports : getGlobal());
 (function(dust){
 
 var parser = (function(){
-  /* Generated by PEG.js 0.6.2 (http://pegjs.majda.cz/). */
+  /*
+   * Generated by PEG.js 0.7.0.
+   *
+   * http://pegjs.majda.cz/
+   */
+  
+  function quote(s) {
+    /*
+     * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a
+     * string literal except for the closing quote character, backslash,
+     * carriage return, line separator, paragraph separator, and line feed.
+     * Any character may appear in the form of an escape sequence.
+     *
+     * For portability, we also escape escape all control and non-ASCII
+     * characters. Note that "\0" and "\v" escape sequences are not used
+     * because JSHint does not like the first and IE the second.
+     */
+     return '"' + s
+      .replace(/\\/g, '\\\\')  // backslash
+      .replace(/"/g, '\\"')    // closing quote character
+      .replace(/\x08/g, '\\b') // backspace
+      .replace(/\t/g, '\\t')   // horizontal tab
+      .replace(/\n/g, '\\n')   // line feed
+      .replace(/\f/g, '\\f')   // form feed
+      .replace(/\r/g, '\\r')   // carriage return
+      .replace(/[\x00-\x07\x0B\x0E-\x1F\x80-\uFFFF]/g, escape)
+      + '"';
+  }
   
   var result = {
     /*
@@ -904,31 +937,31 @@ var parser = (function(){
      */
     parse: function(input, startRule) {
       var parseFunctions = {
-        "bodies": parse_bodies,
         "body": parse_body,
-        "buffer": parse_buffer,
-        "comment": parse_comment,
-        "context": parse_context,
+        "part": parse_part,
+        "section": parse_section,
+        "sec_tag_start": parse_sec_tag_start,
         "end_tag": parse_end_tag,
-        "eol": parse_eol,
-        "esc": parse_esc,
+        "context": parse_context,
+        "params": parse_params,
+        "bodies": parse_bodies,
+        "reference": parse_reference,
+        "partial": parse_partial,
         "filters": parse_filters,
+        "special": parse_special,
         "identifier": parse_identifier,
+        "path": parse_path,
+        "key": parse_key,
         "inline": parse_inline,
         "inline_part": parse_inline_part,
-        "key": parse_key,
-        "ld": parse_ld,
+        "buffer": parse_buffer,
         "literal": parse_literal,
-        "params": parse_params,
-        "part": parse_part,
-        "partial": parse_partial,
-        "path": parse_path,
-        "rd": parse_rd,
-        "reference": parse_reference,
-        "sec_tag_start": parse_sec_tag_start,
-        "section": parse_section,
-        "special": parse_special,
+        "esc": parse_esc,
+        "comment": parse_comment,
         "tag": parse_tag,
+        "ld": parse_ld,
+        "rd": parse_rd,
+        "eol": parse_eol,
         "ws": parse_ws
       };
       
@@ -941,9 +974,9 @@ var parser = (function(){
       }
       
       var pos = 0;
-      var reportMatchFailures = true;
-      var rightmostMatchFailuresPos = 0;
-      var rightmostMatchFailuresExpected = [];
+      var reportFailures = 0;
+      var rightmostFailuresPos = 0;
+      var rightmostFailuresExpected = [];
       var cache = {};
       
       function padLeft(input, padding, length) {
@@ -959,74 +992,57 @@ var parser = (function(){
       
       function escape(ch) {
         var charCode = ch.charCodeAt(0);
+        var escapeChar;
+        var length;
         
         if (charCode <= 0xFF) {
-          var escapeChar = 'x';
-          var length = 2;
+          escapeChar = 'x';
+          length = 2;
         } else {
-          var escapeChar = 'u';
-          var length = 4;
+          escapeChar = 'u';
+          length = 4;
         }
         
         return '\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length);
       }
       
-      function quote(s) {
-        /*
-         * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a
-         * string literal except for the closing quote character, backslash,
-         * carriage return, line separator, paragraph separator, and line feed.
-         * Any character may appear in the form of an escape sequence.
-         */
-        return '"' + s
-          .replace(/\\/g, '\\\\')            // backslash
-          .replace(/"/g, '\\"')              // closing quote character
-          .replace(/\r/g, '\\r')             // carriage return
-          .replace(/\n/g, '\\n')             // line feed
-          .replace(/[\x80-\uFFFF]/g, escape) // non-ASCII characters
-          + '"';
-      }
-      
       function matchFailed(failure) {
-        if (pos < rightmostMatchFailuresPos) {
+        if (pos < rightmostFailuresPos) {
           return;
         }
         
-        if (pos > rightmostMatchFailuresPos) {
-          rightmostMatchFailuresPos = pos;
-          rightmostMatchFailuresExpected = [];
+        if (pos > rightmostFailuresPos) {
+          rightmostFailuresPos = pos;
+          rightmostFailuresExpected = [];
         }
         
-        rightmostMatchFailuresExpected.push(failure);
+        rightmostFailuresExpected.push(failure);
       }
       
       function parse_body() {
-        var cacheKey = 'body@' + pos;
+        var cacheKey = "body@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
+        var result0, result1;
+        var pos0;
         
-        var savedPos0 = pos;
-        var result1 = [];
-        var result3 = parse_part();
-        while (result3 !== null) {
-          result1.push(result3);
-          var result3 = parse_part();
+        pos0 = pos;
+        result0 = [];
+        result1 = parse_part();
+        while (result1 !== null) {
+          result0.push(result1);
+          result1 = parse_part();
         }
-        var result2 = result1 !== null
-          ? (function(p) { return ["body"].concat(p) })(result1)
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
+        if (result0 !== null) {
+          result0 = (function(offset, p) { return ["body"].concat(p) })(pos0, result0);
+        }
+        if (result0 === null) {
+          pos = pos0;
         }
-        
-        
         
         cache[cacheKey] = {
           nextPos: pos,
@@ -1036,48 +1052,32 @@ var parser = (function(){
       }
       
       function parse_part() {
-        var cacheKey = 'part@' + pos;
+        var cacheKey = "part@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
+        var result0;
         
-        var result6 = parse_comment();
-        if (result6 !== null) {
-          var result0 = result6;
-        } else {
-          var result5 = parse_section();
-          if (result5 !== null) {
-            var result0 = result5;
-          } else {
-            var result4 = parse_partial();
-            if (result4 !== null) {
-              var result0 = result4;
-            } else {
-              var result3 = parse_special();
-              if (result3 !== null) {
-                var result0 = result3;
-              } else {
-                var result2 = parse_reference();
-                if (result2 !== null) {
-                  var result0 = result2;
-                } else {
-                  var result1 = parse_buffer();
-                  if (result1 !== null) {
-                    var result0 = result1;
-                  } else {
-                    var result0 = null;;
-                  };
-                };
-              };
-            };
-          };
+        result0 = parse_comment();
+        if (result0 === null) {
+          result0 = parse_section();
+          if (result0 === null) {
+            result0 = parse_partial();
+            if (result0 === null) {
+              result0 = parse_special();
+              if (result0 === null) {
+                result0 = parse_reference();
+                if (result0 === null) {
+                  result0 = parse_buffer();
+                }
+              }
+            }
+          }
         }
         
-        
-        
         cache[cacheKey] = {
           nextPos: pos,
           result:  result0
@@ -1086,112 +1086,112 @@ var parser = (function(){
       }
       
       function parse_section() {
-        var cacheKey = 'section@' + pos;
+        var cacheKey = "section@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
-        var savedReportMatchFailures = reportMatchFailures;
-        reportMatchFailures = false;
-        var savedPos2 = pos;
-        var savedPos3 = pos;
-        var result10 = parse_sec_tag_start();
-        if (result10 !== null) {
-          var result11 = parse_rd();
-          if (result11 !== null) {
-            var result12 = parse_body();
-            if (result12 !== null) {
-              var result13 = parse_bodies();
-              if (result13 !== null) {
-                var result14 = parse_end_tag();
-                if (result14 !== null) {
-                  var result15 = (function() {if (!result8) return true; return result8[1].text === result12.text})() ? '' : null;
-                  if (result15 !== null) {
-                    var result8 = [result10, result11, result12, result13, result14, result15];
+        var result0, result1, result2, result3, result4, result5, result6;
+        var pos0, pos1;
+        
+        reportFailures++;
+        pos0 = pos;
+        pos1 = pos;
+        result0 = parse_sec_tag_start();
+        if (result0 !== null) {
+          result1 = [];
+          result2 = parse_ws();
+          while (result2 !== null) {
+            result1.push(result2);
+            result2 = parse_ws();
+          }
+          if (result1 !== null) {
+            result2 = parse_rd();
+            if (result2 !== null) {
+              result3 = parse_body();
+              if (result3 !== null) {
+                result4 = parse_bodies();
+                if (result4 !== null) {
+                  result5 = parse_end_tag();
+                  if (result5 !== null) {
+                    result6 = (function(offset, t, b, e, n) { return t[1].text === n.text;})(pos, result0, result3, result4, result5) ? "" : null;
+                    if (result6 !== null) {
+                      result0 = [result0, result1, result2, result3, result4, result5, result6];
+                    } else {
+                      result0 = null;
+                      pos = pos1;
+                    }
                   } else {
-                    var result8 = null;
-                    pos = savedPos3;
+                    result0 = null;
+                    pos = pos1;
                   }
                 } else {
-                  var result8 = null;
-                  pos = savedPos3;
+                  result0 = null;
+                  pos = pos1;
                 }
               } else {
-                var result8 = null;
-                pos = savedPos3;
+                result0 = null;
+                pos = pos1;
               }
             } else {
-              var result8 = null;
-              pos = savedPos3;
+              result0 = null;
+              pos = pos1;
             }
           } else {
-            var result8 = null;
-            pos = savedPos3;
+            result0 = null;
+            pos = pos1;
           }
         } else {
-          var result8 = null;
-          pos = savedPos3;
-        }
-        var result9 = result8 !== null
-          ? (function(t, b, e, n) { e.push(["param", ["literal", "block"], b]); t.push(e); return t })(result8[0], result8[2], result8[3], result8[4])
-          : null;
-        if (result9 !== null) {
-          var result7 = result9;
-        } else {
-          var result7 = null;
-          pos = savedPos2;
+          result0 = null;
+          pos = pos1;
         }
-        if (result7 !== null) {
-          var result0 = result7;
-        } else {
-          var savedPos0 = pos;
-          var savedPos1 = pos;
-          var result4 = parse_sec_tag_start();
-          if (result4 !== null) {
-            if (input.substr(pos, 1) === "/") {
-              var result5 = "/";
-              pos += 1;
+        if (result0 !== null) {
+          result0 = (function(offset, t, b, e, n) { e.push(["param", ["literal", "block"], b]); t.push(e); return t })(pos0, result0[0], result0[3], result0[4], result0[5]);
+        }
+        if (result0 === null) {
+          pos = pos0;
+        }
+        if (result0 === null) {
+          pos0 = pos;
+          pos1 = pos;
+          result0 = parse_sec_tag_start();
+          if (result0 !== null) {
+            if (input.charCodeAt(pos) === 47) {
+              result1 = "/";
+              pos++;
             } else {
-              var result5 = null;
-              if (reportMatchFailures) {
+              result1 = null;
+              if (reportFailures === 0) {
                 matchFailed("\"/\"");
               }
             }
-            if (result5 !== null) {
-              var result6 = parse_rd();
-              if (result6 !== null) {
-                var result2 = [result4, result5, result6];
+            if (result1 !== null) {
+              result2 = parse_rd();
+              if (result2 !== null) {
+                result0 = [result0, result1, result2];
               } else {
-                var result2 = null;
-                pos = savedPos1;
+                result0 = null;
+                pos = pos1;
               }
             } else {
-              var result2 = null;
-              pos = savedPos1;
+              result0 = null;
+              pos = pos1;
             }
           } else {
-            var result2 = null;
-            pos = savedPos1;
-          }
-          var result3 = result2 !== null
-            ? (function(t) { t.push(["bodies"]); return t })(result2[0])
-            : null;
-          if (result3 !== null) {
-            var result1 = result3;
-          } else {
-            var result1 = null;
-            pos = savedPos0;
+            result0 = null;
+            pos = pos1;
+          }
+          if (result0 !== null) {
+            result0 = (function(offset, t) { t.push(["bodies"]); return t })(pos0, result0[0]);
+          }
+          if (result0 === null) {
+            pos = pos0;
           }
-          if (result1 !== null) {
-            var result0 = result1;
-          } else {
-            var result0 = null;;
-          };
         }
-        reportMatchFailures = savedReportMatchFailures;
-        if (reportMatchFailures && result0 === null) {
+        reportFailures--;
+        if (reportFailures === 0 && result0 === null) {
           matchFailed("section");
         }
         
@@ -1203,66 +1203,63 @@ var parser = (function(){
       }
       
       function parse_sec_tag_start() {
-        var cacheKey = 'sec_tag_start@' + pos;
+        var cacheKey = "sec_tag_start@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
+        var result0, result1, result2, result3, result4;
+        var pos0, pos1;
         
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var result3 = parse_ld();
-        if (result3 !== null) {
-          if (input.substr(pos).match(/^[#?^<+@%]/) !== null) {
-            var result4 = input.charAt(pos);
+        pos0 = pos;
+        pos1 = pos;
+        result0 = parse_ld();
+        if (result0 !== null) {
+          if (/^[#?^<+@%]/.test(input.charAt(pos))) {
+            result1 = input.charAt(pos);
             pos++;
           } else {
-            var result4 = null;
-            if (reportMatchFailures) {
+            result1 = null;
+            if (reportFailures === 0) {
               matchFailed("[#?^<+@%]");
             }
           }
-          if (result4 !== null) {
-            var result5 = parse_identifier();
-            if (result5 !== null) {
-              var result6 = parse_context();
-              if (result6 !== null) {
-                var result7 = parse_params();
-                if (result7 !== null) {
-                  var result1 = [result3, result4, result5, result6, result7];
+          if (result1 !== null) {
+            result2 = parse_identifier();
+            if (result2 !== null) {
+              result3 = parse_context();
+              if (result3 !== null) {
+                result4 = parse_params();
+                if (result4 !== null) {
+                  result0 = [result0, result1, result2, result3, result4];
                 } else {
-                  var result1 = null;
-                  pos = savedPos1;
+                  result0 = null;
+                  pos = pos1;
                 }
               } else {
-                var result1 = null;
-                pos = savedPos1;
+                result0 = null;
+                pos = pos1;
               }
             } else {
-              var result1 = null;
-              pos = savedPos1;
+              result0 = null;
+              pos = pos1;
             }
           } else {
-            var result1 = null;
-            pos = savedPos1;
+            result0 = null;
+            pos = pos1;
           }
         } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(t, n, c, p) { return [t, n, c, p] })(result1[1], result1[2], result1[3], result1[4])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
+          result0 = null;
+          pos = pos1;
+        }
+        if (result0 !== null) {
+          result0 = (function(offset, t, n, c, p) { return [t, n, c, p] })(pos0, result0[1], result0[2], result0[3], result0[4]);
+        }
+        if (result0 === null) {
+          pos = pos0;
         }
-        
-        
         
         cache[cacheKey] = {
           nextPos: pos,
@@ -1272,61 +1269,60 @@ var parser = (function(){
       }
       
       function parse_end_tag() {
-        var cacheKey = 'end_tag@' + pos;
+        var cacheKey = "end_tag@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
-        var savedReportMatchFailures = reportMatchFailures;
-        reportMatchFailures = false;
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var result3 = parse_ld();
-        if (result3 !== null) {
-          if (input.substr(pos, 1) === "/") {
-            var result4 = "/";
-            pos += 1;
+        var result0, result1, result2, result3;
+        var pos0, pos1;
+        
+        reportFailures++;
+        pos0 = pos;
+        pos1 = pos;
+        result0 = parse_ld();
+        if (result0 !== null) {
+          if (input.charCodeAt(pos) === 47) {
+            result1 = "/";
+            pos++;
           } else {
-            var result4 = null;
-            if (reportMatchFailures) {
+            result1 = null;
+            if (reportFailures === 0) {
               matchFailed("\"/\"");
             }
           }
-          if (result4 !== null) {
-            var result5 = parse_identifier();
-            if (result5 !== null) {
-              var result6 = parse_rd();
-              if (result6 !== null) {
-                var result1 = [result3, result4, result5, result6];
+          if (result1 !== null) {
+            result2 = parse_identifier();
+            if (result2 !== null) {
+              result3 = parse_rd();
+              if (result3 !== null) {
+                result0 = [result0, result1, result2, result3];
               } else {
-                var result1 = null;
-                pos = savedPos1;
+                result0 = null;
+                pos = pos1;
               }
             } else {
-              var result1 = null;
-              pos = savedPos1;
+              result0 = null;
+              pos = pos1;
             }
           } else {
-            var result1 = null;
-            pos = savedPos1;
+            result0 = null;
+            pos = pos1;
           }
         } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(n) { return n })(result1[2])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
+          result0 = null;
+          pos = pos1;
         }
-        reportMatchFailures = savedReportMatchFailures;
-        if (reportMatchFailures && result0 === null) {
+        if (result0 !== null) {
+          result0 = (function(offset, n) { return n })(pos0, result0[2]);
+        }
+        if (result0 === null) {
+          pos = pos0;
+        }
+        reportFailures--;
+        if (reportFailures === 0 && result0 === null) {
           matchFailed("end tag");
         }
         
@@ -1338,59 +1334,53 @@ var parser = (function(){
       }
       
       function parse_context() {
-        var cacheKey = 'context@' + pos;
+        var cacheKey = "context@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
+        var result0, result1;
+        var pos0, pos1, pos2;
         
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var savedPos2 = pos;
-        if (input.substr(pos, 1) === ":") {
-          var result6 = ":";
-          pos += 1;
+        pos0 = pos;
+        pos1 = pos;
+        pos2 = pos;
+        if (input.charCodeAt(pos) === 58) {
+          result0 = ":";
+          pos++;
         } else {
-          var result6 = null;
-          if (reportMatchFailures) {
+          result0 = null;
+          if (reportFailures === 0) {
             matchFailed("\":\"");
           }
         }
-        if (result6 !== null) {
-          var result7 = parse_identifier();
-          if (result7 !== null) {
-            var result4 = [result6, result7];
+        if (result0 !== null) {
+          result1 = parse_identifier();
+          if (result1 !== null) {
+            result0 = [result0, result1];
           } else {
-            var result4 = null;
-            pos = savedPos2;
+            result0 = null;
+            pos = pos2;
           }
         } else {
-          var result4 = null;
-          pos = savedPos2;
-        }
-        var result5 = result4 !== null
-          ? (function(n) {return n})(result4[1])
-          : null;
-        if (result5 !== null) {
-          var result3 = result5;
-        } else {
-          var result3 = null;
-          pos = savedPos1;
-        }
-        var result1 = result3 !== null ? result3 : '';
-        var result2 = result1 !== null
-          ? (function(n) { return n ? ["context", n] : ["context"] })(result1)
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
+          result0 = null;
+          pos = pos2;
+        }
+        if (result0 !== null) {
+          result0 = (function(offset, n) {return n})(pos1, result0[1]);
+        }
+        if (result0 === null) {
+          pos = pos1;
+        }
+        result0 = result0 !== null ? result0 : "";
+        if (result0 !== null) {
+          result0 = (function(offset, n) { return n ? ["context", n] : ["context"] })(pos0, result0);
+        }
+        if (result0 === null) {
+          pos = pos0;
         }
-        
-        
         
         cache[cacheKey] = {
           nextPos: pos,
@@ -1400,139 +1390,118 @@ var parser = (function(){
       }
       
       function parse_params() {
-        var cacheKey = 'params@' + pos;
+        var cacheKey = "params@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
-        var savedReportMatchFailures = reportMatchFailures;
-        reportMatchFailures = false;
-        var savedPos0 = pos;
-        var result1 = [];
-        var savedPos1 = pos;
-        var savedPos2 = pos;
-        var result6 = parse_ws();
-        if (result6 !== null) {
-          var result7 = parse_key();
-          if (result7 !== null) {
-            if (input.substr(pos, 1) === "=") {
-              var result8 = "=";
-              pos += 1;
+        var result0, result1, result2, result3, result4;
+        var pos0, pos1, pos2;
+        
+        reportFailures++;
+        pos0 = pos;
+        result0 = [];
+        pos1 = pos;
+        pos2 = pos;
+        result1 = parse_ws();
+        if (result1 !== null) {
+          result2 = parse_key();
+          if (result2 !== null) {
+            if (input.charCodeAt(pos) === 61) {
+              result3 = "=";
+              pos++;
             } else {
-              var result8 = null;
-              if (reportMatchFailures) {
+              result3 = null;
+              if (reportFailures === 0) {
                 matchFailed("\"=\"");
               }
             }
-            if (result8 !== null) {
-              var result11 = parse_identifier();
-              if (result11 !== null) {
-                var result9 = result11;
-              } else {
-                var result10 = parse_inline();
-                if (result10 !== null) {
-                  var result9 = result10;
-                } else {
-                  var result9 = null;;
-                };
+            if (result3 !== null) {
+              result4 = parse_identifier();
+              if (result4 === null) {
+                result4 = parse_inline();
               }
-              if (result9 !== null) {
-                var result4 = [result6, result7, result8, result9];
+              if (result4 !== null) {
+                result1 = [result1, result2, result3, result4];
               } else {
-                var result4 = null;
-                pos = savedPos2;
+                result1 = null;
+                pos = pos2;
               }
             } else {
-              var result4 = null;
-              pos = savedPos2;
+              result1 = null;
+              pos = pos2;
             }
           } else {
-            var result4 = null;
-            pos = savedPos2;
+            result1 = null;
+            pos = pos2;
           }
         } else {
-          var result4 = null;
-          pos = savedPos2;
-        }
-        var result5 = result4 !== null
-          ? (function(k, v) {return ["param", ["literal", k], v]})(result4[1], result4[3])
-          : null;
-        if (result5 !== null) {
-          var result3 = result5;
-        } else {
-          var result3 = null;
-          pos = savedPos1;
-        }
-        while (result3 !== null) {
-          result1.push(result3);
-          var savedPos1 = pos;
-          var savedPos2 = pos;
-          var result6 = parse_ws();
-          if (result6 !== null) {
-            var result7 = parse_key();
-            if (result7 !== null) {
-              if (input.substr(pos, 1) === "=") {
-                var result8 = "=";
-                pos += 1;
+          result1 = null;
+          pos = pos2;
+        }
+        if (result1 !== null) {
+          result1 = (function(offset, k, v) {return ["param", ["literal", k], v]})(pos1, result1[1], result1[3]);
+        }
+        if (result1 === null) {
+          pos = pos1;
+        }
+        while (result1 !== null) {
+          result0.push(result1);
+          pos1 = pos;
+          pos2 = pos;
+          result1 = parse_ws();
+          if (result1 !== null) {
+            result2 = parse_key();
+            if (result2 !== null) {
+              if (input.charCodeAt(pos) === 61) {
+                result3 = "=";
+                pos++;
               } else {
-                var result8 = null;
-                if (reportMatchFailures) {
+                result3 = null;
+                if (reportFailures === 0) {
                   matchFailed("\"=\"");
                 }
               }
-              if (result8 !== null) {
-                var result11 = parse_identifier();
-                if (result11 !== null) {
-                  var result9 = result11;
-                } else {
-                  var result10 = parse_inline();
-                  if (result10 !== null) {
-                    var result9 = result10;
-                  } else {
-                    var result9 = null;;
-                  };
+              if (result3 !== null) {
+                result4 = parse_identifier();
+                if (result4 === null) {
+                  result4 = parse_inline();
                 }
-                if (result9 !== null) {
-                  var result4 = [result6, result7, result8, result9];
+                if (result4 !== null) {
+                  result1 = [result1, result2, result3, result4];
                 } else {
-                  var result4 = null;
-                  pos = savedPos2;
+                  result1 = null;
+                  pos = pos2;
                 }
               } else {
-                var result4 = null;
-                pos = savedPos2;
+                result1 = null;
+                pos = pos2;
               }
             } else {
-              var result4 = null;
-              pos = savedPos2;
+              result1 = null;
+              pos = pos2;
             }
           } else {
-            var result4 = null;
-            pos = savedPos2;
-          }
-          var result5 = result4 !== null
-            ? (function(k, v) {return ["param", ["literal", k], v]})(result4[1], result4[3])
-            : null;
-          if (result5 !== null) {
-            var result3 = result5;
-          } else {
-            var result3 = null;
-            pos = savedPos1;
+            result1 = null;
+            pos = pos2;
+          }
+          if (result1 !== null) {
+            result1 = (function(offset, k, v) {return ["param", ["literal", k], v]})(pos1, result1[1], result1[3]);
+          }
+          if (result1 === null) {
+            pos = pos1;
           }
         }
-        var result2 = result1 !== null
-          ? (function(p) { return ["params"].concat(p) })(result1)
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
+        if (result0 !== null) {
+          result0 = (function(offset, p) { return ["params"].concat(p) })(pos0, result0);
+        }
+        if (result0 === null) {
+          pos = pos0;
         }
-        reportMatchFailures = savedReportMatchFailures;
-        if (reportMatchFailures && result0 === null) {
+        reportFailures--;
+        if (reportFailures === 0 && result0 === null) {
           matchFailed("params");
         }
         
@@ -1544,131 +1513,124 @@ var parser = (function(){
       }
       
       function parse_bodies() {
-        var cacheKey = 'bodies@' + pos;
+        var cacheKey = "bodies@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
-        var savedReportMatchFailures = reportMatchFailures;
-        reportMatchFailures = false;
-        var savedPos0 = pos;
-        var result1 = [];
-        var savedPos1 = pos;
-        var savedPos2 = pos;
-        var result6 = parse_ld();
-        if (result6 !== null) {
-          if (input.substr(pos, 1) === ":") {
-            var result7 = ":";
-            pos += 1;
+        var result0, result1, result2, result3, result4, result5;
+        var pos0, pos1, pos2;
+        
+        reportFailures++;
+        pos0 = pos;
+        result0 = [];
+        pos1 = pos;
+        pos2 = pos;
+        result1 = parse_ld();
+        if (result1 !== null) {
+          if (input.charCodeAt(pos) === 58) {
+            result2 = ":";
+            pos++;
           } else {
-            var result7 = null;
-            if (reportMatchFailures) {
+            result2 = null;
+            if (reportFailures === 0) {
               matchFailed("\":\"");
             }
           }
-          if (result7 !== null) {
-            var result8 = parse_key();
-            if (result8 !== null) {
-              var result9 = parse_rd();
-              if (result9 !== null) {
-                var result10 = parse_body();
-                if (result10 !== null) {
-                  var result4 = [result6, result7, result8, result9, result10];
+          if (result2 !== null) {
+            result3 = parse_key();
+            if (result3 !== null) {
+              result4 = parse_rd();
+              if (result4 !== null) {
+                result5 = parse_body();
+                if (result5 !== null) {
+                  result1 = [result1, result2, result3, result4, result5];
                 } else {
-                  var result4 = null;
-                  pos = savedPos2;
+                  result1 = null;
+                  pos = pos2;
                 }
               } else {
-                var result4 = null;
-                pos = savedPos2;
+                result1 = null;
+                pos = pos2;
               }
             } else {
-              var result4 = null;
-              pos = savedPos2;
+              result1 = null;
+              pos = pos2;
             }
           } else {
-            var result4 = null;
-            pos = savedPos2;
+            result1 = null;
+            pos = pos2;
           }
         } else {
-          var result4 = null;
-          pos = savedPos2;
-        }
-        var result5 = result4 !== null
-          ? (function(k, v) {return ["param", ["literal", k], v]})(result4[2], result4[4])
-          : null;
-        if (result5 !== null) {
-          var result3 = result5;
-        } else {
-          var result3 = null;
-          pos = savedPos1;
-        }
-        while (result3 !== null) {
-          result1.push(result3);
-          var savedPos1 = pos;
-          var savedPos2 = pos;
-          var result6 = parse_ld();
-          if (result6 !== null) {
-            if (input.substr(pos, 1) === ":") {
-              var result7 = ":";
-              pos += 1;
+          result1 = null;
+          pos = pos2;
+        }
+        if (result1 !== null) {
+          result1 = (function(offset, k, v) {return ["param", ["literal", k], v]})(pos1, result1[2], result1[4]);
+        }
+        if (result1 === null) {
+          pos = pos1;
+        }
+        while (result1 !== null) {
+          result0.push(result1);
+          pos1 = pos;
+          pos2 = pos;
+          result1 = parse_ld();
+          if (result1 !== null) {
+            if (input.charCodeAt(pos) === 58) {
+              result2 = ":";
+              pos++;
             } else {
-              var result7 = null;
-              if (reportMatchFailures) {
+              result2 = null;
+              if (reportFailures === 0) {
                 matchFailed("\":\"");
               }
             }
-            if (result7 !== null) {
-              var result8 = parse_key();
-              if (result8 !== null) {
-                var result9 = parse_rd();
-                if (result9 !== null) {
-                  var result10 = parse_body();
-                  if (result10 !== null) {
-                    var result4 = [result6, result7, result8, result9, result10];
+            if (result2 !== null) {
+              result3 = parse_key();
+              if (result3 !== null) {
+                result4 = parse_rd();
+                if (result4 !== null) {
+                  result5 = parse_body();
+                  if (result5 !== null) {
+                    result1 = [result1, result2, result3, result4, result5];
                   } else {
-                    var result4 = null;
-                    pos = savedPos2;
+                    result1 = null;
+                    pos = pos2;
                   }
                 } else {
-                  var result4 = null;
-                  pos = savedPos2;
+                  result1 = null;
+                  pos = pos2;
                 }
               } else {
-                var result4 = null;
-                pos = savedPos2;
+                result1 = null;
+                pos = pos2;
               }
             } else {
-              var result4 = null;
-              pos = savedPos2;
+              result1 = null;
+              pos = pos2;
             }
           } else {
-            var result4 = null;
-            pos = savedPos2;
-          }
-          var result5 = result4 !== null
-            ? (function(k, v) {return ["param", ["literal", k], v]})(result4[2], result4[4])
-            : null;
-          if (result5 !== null) {
-            var result3 = result5;
-          } else {
-            var result3 = null;
-            pos = savedPos1;
+            result1 = null;
+            pos = pos2;
+          }
+          if (result1 !== null) {
+            result1 = (function(offset, k, v) {return ["param", ["literal", k], v]})(pos1, result1[2], result1[4]);
+          }
+          if (result1 === null) {
+            pos = pos1;
           }
         }
-        var result2 = result1 !== null
-          ? (function(p) { return ["bodies"].concat(p) })(result1)
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
+        if (result0 !== null) {
+          result0 = (function(offset, p) { return ["bodies"].concat(p) })(pos0, result0);
         }
-        reportMatchFailures = savedReportMatchFailures;
-        if (reportMatchFailures && result0 === null) {
+        if (result0 === null) {
+          pos = pos0;
+        }
+        reportFailures--;
+        if (reportFailures === 0 && result0 === null) {
           matchFailed("bodies");
         }
         
@@ -1680,53 +1642,52 @@ var parser = (function(){
       }
       
       function parse_reference() {
-        var cacheKey = 'reference@' + pos;
+        var cacheKey = "reference@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
-        var savedReportMatchFailures = reportMatchFailures;
-        reportMatchFailures = false;
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var result3 = parse_ld();
-        if (result3 !== null) {
-          var result4 = parse_identifier();
-          if (result4 !== null) {
-            var result5 = parse_filters();
-            if (result5 !== null) {
-              var result6 = parse_rd();
-              if (result6 !== null) {
-                var result1 = [result3, result4, result5, result6];
+        var result0, result1, result2, result3;
+        var pos0, pos1;
+        
+        reportFailures++;
+        pos0 = pos;
+        pos1 = pos;
+        result0 = parse_ld();
+        if (result0 !== null) {
+          result1 = parse_identifier();
+          if (result1 !== null) {
+            result2 = parse_filters();
+            if (result2 !== null) {
+              result3 = parse_rd();
+              if (result3 !== null) {
+                result0 = [result0, result1, result2, result3];
               } else {
-                var result1 = null;
-                pos = savedPos1;
+                result0 = null;
+                pos = pos1;
               }
             } else {
-              var result1 = null;
-              pos = savedPos1;
+              result0 = null;
+              pos = pos1;
             }
           } else {
-            var result1 = null;
-            pos = savedPos1;
+            result0 = null;
+            pos = pos1;
           }
         } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(n, f) { return ["reference", n, f] })(result1[1], result1[2])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
+          result0 = null;
+          pos = pos1;
+        }
+        if (result0 !== null) {
+          result0 = (function(offset, n, f) { return ["reference", n, f] })(pos0, result0[1], result0[2]);
         }
-        reportMatchFailures = savedReportMatchFailures;
-        if (reportMatchFailures && result0 === null) {
+        if (result0 === null) {
+          pos = pos0;
+        }
+        reportFailures--;
+        if (reportFailures === 0 && result0 === null) {
           matchFailed("reference");
         }
         
@@ -1738,101 +1699,90 @@ var parser = (function(){
       }
       
       function parse_partial() {
-        var cacheKey = 'partial@' + pos;
+        var cacheKey = "partial@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
-        var savedReportMatchFailures = reportMatchFailures;
-        reportMatchFailures = false;
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var result3 = parse_ld();
-        if (result3 !== null) {
-          if (input.substr(pos, 1) === ">") {
-            var result4 = ">";
-            pos += 1;
+        var result0, result1, result2, result3, result4, result5;
+        var pos0, pos1, pos2;
+        
+        reportFailures++;
+        pos0 = pos;
+        pos1 = pos;
+        result0 = parse_ld();
+        if (result0 !== null) {
+          if (input.charCodeAt(pos) === 62) {
+            result1 = ">";
+            pos++;
           } else {
-            var result4 = null;
-            if (reportMatchFailures) {
+            result1 = null;
+            if (reportFailures === 0) {
               matchFailed("\">\"");
             }
           }
-          if (result4 !== null) {
-            var savedPos2 = pos;
-            var result11 = parse_key();
-            var result12 = result11 !== null
-              ? (function(k) {return ["literal", k]})(result11)
-              : null;
-            if (result12 !== null) {
-              var result10 = result12;
-            } else {
-              var result10 = null;
-              pos = savedPos2;
+          if (result1 !== null) {
+            pos2 = pos;
+            result2 = parse_key();
+            if (result2 !== null) {
+              result2 = (function(offset, k) {return ["literal", k]})(pos2, result2);
             }
-            if (result10 !== null) {
-              var result5 = result10;
-            } else {
-              var result9 = parse_inline();
-              if (result9 !== null) {
-                var result5 = result9;
-              } else {
-                var result5 = null;;
-              };
-            }
-            if (result5 !== null) {
-              var result6 = parse_context();
-              if (result6 !== null) {
-                if (input.substr(pos, 1) === "/") {
-                  var result7 = "/";
-                  pos += 1;
+            if (result2 === null) {
+              pos = pos2;
+            }
+            if (result2 === null) {
+              result2 = parse_inline();
+            }
+            if (result2 !== null) {
+              result3 = parse_context();
+              if (result3 !== null) {
+                if (input.charCodeAt(pos) === 47) {
+                  result4 = "/";
+                  pos++;
                 } else {
-                  var result7 = null;
-                  if (reportMatchFailures) {
+                  result4 = null;
+                  if (reportFailures === 0) {
                     matchFailed("\"/\"");
                   }
                 }
-                if (result7 !== null) {
-                  var result8 = parse_rd();
-                  if (result8 !== null) {
-                    var result1 = [result3, result4, result5, result6, result7, result8];
+                if (result4 !== null) {
+                  result5 = parse_rd();
+                  if (result5 !== null) {
+                    result0 = [result0, result1, result2, result3, result4, result5];
                   } else {
-                    var result1 = null;
-                    pos = savedPos1;
+                    result0 = null;
+                    pos = pos1;
                   }
                 } else {
-                  var result1 = null;
-                  pos = savedPos1;
+                  result0 = null;
+                  pos = pos1;
                 }
               } else {
-                var result1 = null;
-                pos = savedPos1;
+                result0 = null;
+                pos = pos1;
               }
             } else {
-              var result1 = null;
-              pos = savedPos1;
+              result0 = null;
+              pos = pos1;
             }
           } else {
-            var result1 = null;
-            pos = savedPos1;
+            result0 = null;
+            pos = pos1;
           }
         } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(n, c) { return ["partial", n, c] })(result1[2], result1[3])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
+          result0 = null;
+          pos = pos1;
         }
-        reportMatchFailures = savedReportMatchFailures;
-        if (reportMatchFailures && result0 === null) {
+        if (result0 !== null) {
+          result0 = (function(offset, n, c) { return ["partial", n, c] })(pos0, result0[2], result0[3]);
+        }
+        if (result0 === null) {
+          pos = pos0;
+        }
+        reportFailures--;
+        if (reportFailures === 0 && result0 === null) {
           matchFailed("partial");
         }
         
@@ -1844,95 +1794,88 @@ var parser = (function(){
       }
       
       function parse_filters() {
-        var cacheKey = 'filters@' + pos;
+        var cacheKey = "filters@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
-        var savedReportMatchFailures = reportMatchFailures;
-        reportMatchFailures = false;
-        var savedPos0 = pos;
-        var result1 = [];
-        var savedPos1 = pos;
-        var savedPos2 = pos;
-        if (input.substr(pos, 1) === "|") {
-          var result6 = "|";
-          pos += 1;
+        var result0, result1, result2;
+        var pos0, pos1, pos2;
+        
+        reportFailures++;
+        pos0 = pos;
+        result0 = [];
+        pos1 = pos;
+        pos2 = pos;
+        if (input.charCodeAt(pos) === 124) {
+          result1 = "|";
+          pos++;
         } else {
-          var result6 = null;
-          if (reportMatchFailures) {
+          result1 = null;
+          if (reportFailures === 0) {
             matchFailed("\"|\"");
           }
         }
-        if (result6 !== null) {
-          var result7 = parse_key();
-          if (result7 !== null) {
-            var result4 = [result6, result7];
+        if (result1 !== null) {
+          result2 = parse_key();
+          if (result2 !== null) {
+            result1 = [result1, result2];
           } else {
-            var result4 = null;
-            pos = savedPos2;
+            result1 = null;
+            pos = pos2;
           }
         } else {
-          var result4 = null;
-          pos = savedPos2;
-        }
-        var result5 = result4 !== null
-          ? (function(n) {return n})(result4[1])
-          : null;
-        if (result5 !== null) {
-          var result3 = result5;
-        } else {
-          var result3 = null;
-          pos = savedPos1;
-        }
-        while (result3 !== null) {
-          result1.push(result3);
-          var savedPos1 = pos;
-          var savedPos2 = pos;
-          if (input.substr(pos, 1) === "|") {
-            var result6 = "|";
-            pos += 1;
+          result1 = null;
+          pos = pos2;
+        }
+        if (result1 !== null) {
+          result1 = (function(offset, n) {return n})(pos1, result1[1]);
+        }
+        if (result1 === null) {
+          pos = pos1;
+        }
+        while (result1 !== null) {
+          result0.push(result1);
+          pos1 = pos;
+          pos2 = pos;
+          if (input.charCodeAt(pos) === 124) {
+            result1 = "|";
+            pos++;
           } else {
-            var result6 = null;
-            if (reportMatchFailures) {
+            result1 = null;
+            if (reportFailures === 0) {
               matchFailed("\"|\"");
             }
           }
-          if (result6 !== null) {
-            var result7 = parse_key();
-            if (result7 !== null) {
-              var result4 = [result6, result7];
+          if (result1 !== null) {
+            result2 = parse_key();
+            if (result2 !== null) {
+              result1 = [result1, result2];
             } else {
-              var result4 = null;
-              pos = savedPos2;
+              result1 = null;
+              pos = pos2;
             }
           } else {
-            var result4 = null;
-            pos = savedPos2;
-          }
-          var result5 = result4 !== null
-            ? (function(n) {return n})(result4[1])
-            : null;
-          if (result5 !== null) {
-            var result3 = result5;
-          } else {
-            var result3 = null;
-            pos = savedPos1;
+            result1 = null;
+            pos = pos2;
+          }
+          if (result1 !== null) {
+            result1 = (function(offset, n) {return n})(pos1, result1[1]);
+          }
+          if (result1 === null) {
+            pos = pos1;
           }
         }
-        var result2 = result1 !== null
-          ? (function(f) { return ["filters"].concat(f) })(result1)
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
+        if (result0 !== null) {
+          result0 = (function(offset, f) { return ["filters"].concat(f) })(pos0, result0);
+        }
+        if (result0 === null) {
+          pos = pos0;
         }
-        reportMatchFailures = savedReportMatchFailures;
-        if (reportMatchFailures && result0 === null) {
+        reportFailures--;
+        if (reportFailures === 0 && result0 === null) {
           matchFailed("filters");
         }
         
@@ -1944,61 +1887,60 @@ var parser = (function(){
       }
       
       function parse_special() {
-        var cacheKey = 'special@' + pos;
+        var cacheKey = "special@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
-        var savedReportMatchFailures = reportMatchFailures;
-        reportMatchFailures = false;
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var result3 = parse_ld();
-        if (result3 !== null) {
-          if (input.substr(pos, 1) === "~") {
-            var result4 = "~";
-            pos += 1;
+        var result0, result1, result2, result3;
+        var pos0, pos1;
+        
+        reportFailures++;
+        pos0 = pos;
+        pos1 = pos;
+        result0 = parse_ld();
+        if (result0 !== null) {
+          if (input.charCodeAt(pos) === 126) {
+            result1 = "~";
+            pos++;
           } else {
-            var result4 = null;
-            if (reportMatchFailures) {
+            result1 = null;
+            if (reportFailures === 0) {
               matchFailed("\"~\"");
             }
           }
-          if (result4 !== null) {
-            var result5 = parse_key();
-            if (result5 !== null) {
-              var result6 = parse_rd();
-              if (result6 !== null) {
-                var result1 = [result3, result4, result5, result6];
+          if (result1 !== null) {
+            result2 = parse_key();
+            if (result2 !== null) {
+              result3 = parse_rd();
+              if (result3 !== null) {
+                result0 = [result0, result1, result2, result3];
               } else {
-                var result1 = null;
-                pos = savedPos1;
+                result0 = null;
+                pos = pos1;
               }
             } else {
-              var result1 = null;
-              pos = savedPos1;
+              result0 = null;
+              pos = pos1;
             }
           } else {
-            var result1 = null;
-            pos = savedPos1;
+            result0 = null;
+            pos = pos1;
           }
         } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(k) { return ["special", k] })(result1[2])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
+          result0 = null;
+          pos = pos1;
+        }
+        if (result0 !== null) {
+          result0 = (function(offset, k) { return ["special", k] })(pos0, result0[2]);
         }
-        reportMatchFailures = savedReportMatchFailures;
-        if (reportMatchFailures && result0 === null) {
+        if (result0 === null) {
+          pos = pos0;
+        }
+        reportFailures--;
+        if (reportFailures === 0 && result0 === null) {
           matchFailed("special");
         }
         
@@ -2010,48 +1952,37 @@ var parser = (function(){
       }
       
       function parse_identifier() {
-        var cacheKey = 'identifier@' + pos;
+        var cacheKey = "identifier@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
-        var savedReportMatchFailures = reportMatchFailures;
-        reportMatchFailures = false;
-        var savedPos1 = pos;
-        var result5 = parse_path();
-        var result6 = result5 !== null
-          ? (function(p) { return wrap(["path"].concat(p), cacheKey) })(result5)
-          : null;
-        if (result6 !== null) {
-          var result4 = result6;
-        } else {
-          var result4 = null;
-          pos = savedPos1;
+        var result0;
+        var pos0;
+        
+        reportFailures++;
+        pos0 = pos;
+        result0 = parse_path();
+        if (result0 !== null) {
+          result0 = (function(offset, p) { return wrap(["path"].concat(p), cacheKey) })(pos0, result0);
         }
-        if (result4 !== null) {
-          var result0 = result4;
-        } else {
-          var savedPos0 = pos;
-          var result2 = parse_key();
-          var result3 = result2 !== null
-            ? (function(k) { return wrap(["key", k], cacheKey) })(result2)
-            : null;
-          if (result3 !== null) {
-            var result1 = result3;
-          } else {
-            var result1 = null;
-            pos = savedPos0;
+        if (result0 === null) {
+          pos = pos0;
+        }
+        if (result0 === null) {
+          pos0 = pos;
+          result0 = parse_key();
+          if (result0 !== null) {
+            result0 = (function(offset, k) { return wrap(["key", k], cacheKey) })(pos0, result0);
+          }
+          if (result0 === null) {
+            pos = pos0;
           }
-          if (result1 !== null) {
-            var result0 = result1;
-          } else {
-            var result0 = null;;
-          };
         }
-        reportMatchFailures = savedReportMatchFailures;
-        if (reportMatchFailures && result0 === null) {
+        reportFailures--;
+        if (reportFailures === 0 && result0 === null) {
           matchFailed("identifier");
         }
         
@@ -2063,144 +1994,127 @@ var parser = (function(){
       }
       
       function parse_path() {
-        var cacheKey = 'path@' + pos;
+        var cacheKey = "path@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
-        var savedReportMatchFailures = reportMatchFailures;
-        reportMatchFailures = false;
-        var savedPos1 = pos;
-        var savedPos2 = pos;
-        var result14 = parse_key();
-        var result7 = result14 !== null ? result14 : '';
-        if (result7 !== null) {
-          var savedPos3 = pos;
-          var savedPos4 = pos;
-          if (input.substr(pos, 1) === ".") {
-            var result12 = ".";
-            pos += 1;
+        var result0, result1, result2, result3;
+        var pos0, pos1, pos2, pos3;
+        
+        reportFailures++;
+        pos0 = pos;
+        pos1 = pos;
+        result0 = parse_key();
+        result0 = result0 !== null ? result0 : "";
+        if (result0 !== null) {
+          pos2 = pos;
+          pos3 = pos;
+          if (input.charCodeAt(pos) === 46) {
+            result2 = ".";
+            pos++;
           } else {
-            var result12 = null;
-            if (reportMatchFailures) {
+            result2 = null;
+            if (reportFailures === 0) {
               matchFailed("\".\"");
             }
           }
-          if (result12 !== null) {
-            var result13 = parse_key();
-            if (result13 !== null) {
-              var result10 = [result12, result13];
+          if (result2 !== null) {
+            result3 = parse_key();
+            if (result3 !== null) {
+              result2 = [result2, result3];
             } else {
-              var result10 = null;
-              pos = savedPos4;
+              result2 = null;
+              pos = pos3;
             }
           } else {
-            var result10 = null;
-            pos = savedPos4;
-          }
-          var result11 = result10 !== null
-            ? (function(k) {return k})(result10[1])
-            : null;
-          if (result11 !== null) {
-            var result9 = result11;
-          } else {
-            var result9 = null;
-            pos = savedPos3;
-          }
-          if (result9 !== null) {
-            var result8 = [];
-            while (result9 !== null) {
-              result8.push(result9);
-              var savedPos3 = pos;
-              var savedPos4 = pos;
-              if (input.substr(pos, 1) === ".") {
-                var result12 = ".";
-                pos += 1;
+            result2 = null;
+            pos = pos3;
+          }
+          if (result2 !== null) {
+            result2 = (function(offset, k) {return k})(pos2, result2[1]);
+          }
+          if (result2 === null) {
+            pos = pos2;
+          }
+          if (result2 !== null) {
+            result1 = [];
+            while (result2 !== null) {
+              result1.push(result2);
+              pos2 = pos;
+              pos3 = pos;
+              if (input.charCodeAt(pos) === 46) {
+                result2 = ".";
+                pos++;
               } else {
-                var result12 = null;
-                if (reportMatchFailures) {
+                result2 = null;
+                if (reportFailures === 0) {
                   matchFailed("\".\"");
                 }
               }
-              if (result12 !== null) {
-                var result13 = parse_key();
-                if (result13 !== null) {
-                  var result10 = [result12, result13];
+              if (result2 !== null) {
+                result3 = parse_key();
+                if (result3 !== null) {
+                  result2 = [result2, result3];
                 } else {
-                  var result10 = null;
-                  pos = savedPos4;
+                  result2 = null;
+                  pos = pos3;
                 }
               } else {
-                var result10 = null;
-                pos = savedPos4;
+                result2 = null;
+                pos = pos3;
               }
-              var result11 = result10 !== null
-                ? (function(k) {return k})(result10[1])
-                : null;
-              if (result11 !== null) {
-                var result9 = result11;
-              } else {
-                var result9 = null;
-                pos = savedPos3;
+              if (result2 !== null) {
+                result2 = (function(offset, k) {return k})(pos2, result2[1]);
+              }
+              if (result2 === null) {
+                pos = pos2;
               }
             }
           } else {
-            var result8 = null;
+            result1 = null;
           }
-          if (result8 !== null) {
-            var result5 = [result7, result8];
+          if (result1 !== null) {
+            result0 = [result0, result1];
           } else {
-            var result5 = null;
-            pos = savedPos2;
+            result0 = null;
+            pos = pos1;
           }
         } else {
-          var result5 = null;
-          pos = savedPos2;
-        }
-        var result6 = result5 !== null
-          ? (function(k, d) {
-              if (k) { d.unshift(k); return [false, d]; }
-              return [true, d];
-            })(result5[0], result5[1])
-          : null;
-        if (result6 !== null) {
-          var result4 = result6;
-        } else {
-          var result4 = null;
-          pos = savedPos1;
+          result0 = null;
+          pos = pos1;
         }
-        if (result4 !== null) {
-          var result0 = result4;
-        } else {
-          var savedPos0 = pos;
-          if (input.substr(pos, 1) === ".") {
-            var result2 = ".";
-            pos += 1;
+        if (result0 !== null) {
+          result0 = (function(offset, k, d) {
+            if (k) { d.unshift(k); return [false, d]; }
+            return [true, d];
+          })(pos0, result0[0], result0[1]);
+        }
+        if (result0 === null) {
+          pos = pos0;
+        }
+        if (result0 === null) {
+          pos0 = pos;
+          if (input.charCodeAt(pos) === 46) {
+            result0 = ".";
+            pos++;
           } else {
-            var result2 = null;
-            if (reportMatchFailures) {
+            result0 = null;
+            if (reportFailures === 0) {
               matchFailed("\".\"");
             }
           }
-          var result3 = result2 !== null
-            ? (function() { return [true, []] })()
-            : null;
-          if (result3 !== null) {
-            var result1 = result3;
-          } else {
-            var result1 = null;
-            pos = savedPos0;
+          if (result0 !== null) {
+            result0 = (function(offset) { return [true, []] })(pos0);
+          }
+          if (result0 === null) {
+            pos = pos0;
           }
-          if (result1 !== null) {
-            var result0 = result1;
-          } else {
-            var result0 = null;;
-          };
         }
-        reportMatchFailures = savedReportMatchFailures;
-        if (reportMatchFailures && result0 === null) {
+        reportFailures--;
+        if (reportFailures === 0 && result0 === null) {
           matchFailed("path");
         }
         
@@ -2212,70 +2126,69 @@ var parser = (function(){
       }
       
       function parse_key() {
-        var cacheKey = 'key@' + pos;
+        var cacheKey = "key@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
-        var savedReportMatchFailures = reportMatchFailures;
-        reportMatchFailures = false;
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        if (input.substr(pos).match(/^[a-zA-Z_$]/) !== null) {
-          var result3 = input.charAt(pos);
+        var result0, result1, result2;
+        var pos0, pos1;
+        
+        reportFailures++;
+        pos0 = pos;
+        pos1 = pos;
+        if (/^[a-zA-Z_$]/.test(input.charAt(pos))) {
+          result0 = input.charAt(pos);
           pos++;
         } else {
-          var result3 = null;
-          if (reportMatchFailures) {
+          result0 = null;
+          if (reportFailures === 0) {
             matchFailed("[a-zA-Z_$]");
           }
         }
-        if (result3 !== null) {
-          var result4 = [];
-          if (input.substr(pos).match(/^[0-9a-zA-Z_$]/) !== null) {
-            var result5 = input.charAt(pos);
+        if (result0 !== null) {
+          result1 = [];
+          if (/^[0-9a-zA-Z_$]/.test(input.charAt(pos))) {
+            result2 = input.charAt(pos);
             pos++;
           } else {
-            var result5 = null;
-            if (reportMatchFailures) {
+            result2 = null;
+            if (reportFailures === 0) {
               matchFailed("[0-9a-zA-Z_$]");
             }
           }
-          while (result5 !== null) {
-            result4.push(result5);
-            if (input.substr(pos).match(/^[0-9a-zA-Z_$]/) !== null) {
-              var result5 = input.charAt(pos);
+          while (result2 !== null) {
+            result1.push(result2);
+            if (/^[0-9a-zA-Z_$]/.test(input.charAt(pos))) {
+              result2 = input.charAt(pos);
               pos++;
             } else {
-              var result5 = null;
-              if (reportMatchFailures) {
+              result2 = null;
+              if (reportFailures === 0) {
                 matchFailed("[0-9a-zA-Z_$]");
               }
             }
           }
-          if (result4 !== null) {
-            var result1 = [result3, result4];
+          if (result1 !== null) {
+            result0 = [result0, result1];
           } else {
-            var result1 = null;
-            pos = savedPos1;
+            result0 = null;
+            pos = pos1;
           }
         } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(h, t) { return h + t.join('') })(result1[0], result1[1])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
+          result0 = null;
+          pos = pos1;
         }
-        reportMatchFailures = savedReportMatchFailures;
-        if (reportMatchFailures && result0 === null) {
+        if (result0 !== null) {
+          result0 = (function(offset, h, t) { return h + t.join('') })(pos0, result0[0], result0[1]);
+        }
+        if (result0 === null) {
+          pos = pos0;
+        }
+        reportFailures--;
+        if (reportFailures === 0 && result0 === null) {
           matchFailed("key");
         }
         
@@ -2287,171 +2200,155 @@ var parser = (function(){
       }
       
       function parse_inline() {
-        var cacheKey = 'inline@' + pos;
+        var cacheKey = "inline@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
-        var savedReportMatchFailures = reportMatchFailures;
-        reportMatchFailures = false;
-        var savedPos4 = pos;
-        var savedPos5 = pos;
-        if (input.substr(pos, 1) === "\"") {
-          var result17 = "\"";
-          pos += 1;
+        var result0, result1, result2;
+        var pos0, pos1;
+        
+        reportFailures++;
+        pos0 = pos;
+        pos1 = pos;
+        if (input.charCodeAt(pos) === 34) {
+          result0 = "\"";
+          pos++;
         } else {
-          var result17 = null;
-          if (reportMatchFailures) {
+          result0 = null;
+          if (reportFailures === 0) {
             matchFailed("\"\\\"\"");
           }
         }
-        if (result17 !== null) {
-          if (input.substr(pos, 1) === "\"") {
-            var result18 = "\"";
-            pos += 1;
+        if (result0 !== null) {
+          if (input.charCodeAt(pos) === 34) {
+            result1 = "\"";
+            pos++;
           } else {
-            var result18 = null;
-            if (reportMatchFailures) {
+            result1 = null;
+            if (reportFailures === 0) {
               matchFailed("\"\\\"\"");
             }
           }
-          if (result18 !== null) {
-            var result15 = [result17, result18];
+          if (result1 !== null) {
+            result0 = [result0, result1];
           } else {
-            var result15 = null;
-            pos = savedPos5;
+            result0 = null;
+            pos = pos1;
           }
         } else {
-          var result15 = null;
-          pos = savedPos5;
-        }
-        var result16 = result15 !== null
-          ? (function() { return ["literal", ""] })()
-          : null;
-        if (result16 !== null) {
-          var result14 = result16;
-        } else {
-          var result14 = null;
-          pos = savedPos4;
+          result0 = null;
+          pos = pos1;
         }
-        if (result14 !== null) {
-          var result0 = result14;
-        } else {
-          var savedPos2 = pos;
-          var savedPos3 = pos;
-          if (input.substr(pos, 1) === "\"") {
-            var result11 = "\"";
-            pos += 1;
+        if (result0 !== null) {
+          result0 = (function(offset) { return ["literal", ""] })(pos0);
+        }
+        if (result0 === null) {
+          pos = pos0;
+        }
+        if (result0 === null) {
+          pos0 = pos;
+          pos1 = pos;
+          if (input.charCodeAt(pos) === 34) {
+            result0 = "\"";
+            pos++;
           } else {
-            var result11 = null;
-            if (reportMatchFailures) {
+            result0 = null;
+            if (reportFailures === 0) {
               matchFailed("\"\\\"\"");
             }
           }
-          if (result11 !== null) {
-            var result12 = parse_literal();
-            if (result12 !== null) {
-              if (input.substr(pos, 1) === "\"") {
-                var result13 = "\"";
-                pos += 1;
+          if (result0 !== null) {
+            result1 = parse_literal();
+            if (result1 !== null) {
+              if (input.charCodeAt(pos) === 34) {
+                result2 = "\"";
+                pos++;
               } else {
-                var result13 = null;
-                if (reportMatchFailures) {
+                result2 = null;
+                if (reportFailures === 0) {
                   matchFailed("\"\\\"\"");
                 }
               }
-              if (result13 !== null) {
-                var result9 = [result11, result12, result13];
+              if (result2 !== null) {
+                result0 = [result0, result1, result2];
               } else {
-                var result9 = null;
-                pos = savedPos3;
+                result0 = null;
+                pos = pos1;
               }
             } else {
-              var result9 = null;
-              pos = savedPos3;
+              result0 = null;
+              pos = pos1;
             }
           } else {
-            var result9 = null;
-            pos = savedPos3;
-          }
-          var result10 = result9 !== null
-            ? (function(l) { return ["literal", l] })(result9[1])
-            : null;
-          if (result10 !== null) {
-            var result8 = result10;
-          } else {
-            var result8 = null;
-            pos = savedPos2;
+            result0 = null;
+            pos = pos1;
           }
-          if (result8 !== null) {
-            var result0 = result8;
-          } else {
-            var savedPos0 = pos;
-            var savedPos1 = pos;
-            if (input.substr(pos, 1) === "\"") {
-              var result4 = "\"";
-              pos += 1;
+          if (result0 !== null) {
+            result0 = (function(offset, l) { return ["literal", l] })(pos0, result0[1]);
+          }
+          if (result0 === null) {
+            pos = pos0;
+          }
+          if (result0 === null) {
+            pos0 = pos;
+            pos1 = pos;
+            if (input.charCodeAt(pos) === 34) {
+              result0 = "\"";
+              pos++;
             } else {
-              var result4 = null;
-              if (reportMatchFailures) {
+              result0 = null;
+              if (reportFailures === 0) {
                 matchFailed("\"\\\"\"");
               }
             }
-            if (result4 !== null) {
-              var result7 = parse_inline_part();
-              if (result7 !== null) {
-                var result5 = [];
-                while (result7 !== null) {
-                  result5.push(result7);
-                  var result7 = parse_inline_part();
+            if (result0 !== null) {
+              result2 = parse_inline_part();
+              if (result2 !== null) {
+                result1 = [];
+                while (result2 !== null) {
+                  result1.push(result2);
+                  result2 = parse_inline_part();
                 }
               } else {
-                var result5 = null;
+                result1 = null;
               }
-              if (result5 !== null) {
-                if (input.substr(pos, 1) === "\"") {
-                  var result6 = "\"";
-                  pos += 1;
+              if (result1 !== null) {
+                if (input.charCodeAt(pos) === 34) {
+                  result2 = "\"";
+                  pos++;
                 } else {
-                  var result6 = null;
-                  if (reportMatchFailures) {
+                  result2 = null;
+                  if (reportFailures === 0) {
                     matchFailed("\"\\\"\"");
                   }
                 }
-                if (result6 !== null) {
-                  var result2 = [result4, result5, result6];
+                if (result2 !== null) {
+                  result0 = [result0, result1, result2];
                 } else {
-                  var result2 = null;
-                  pos = savedPos1;
+                  result0 = null;
+                  pos = pos1;
                 }
               } else {
-                var result2 = null;
-                pos = savedPos1;
+                result0 = null;
+                pos = pos1;
               }
             } else {
-              var result2 = null;
-              pos = savedPos1;
+              result0 = null;
+              pos = pos1;
             }
-            var result3 = result2 !== null
-              ? (function(p) { return ["body"].concat(p) })(result2[1])
-              : null;
-            if (result3 !== null) {
-              var result1 = result3;
-            } else {
-              var result1 = null;
-              pos = savedPos0;
+            if (result0 !== null) {
+              result0 = (function(offset, p) { return ["body"].concat(p) })(pos0, result0[1]);
             }
-            if (result1 !== null) {
-              var result0 = result1;
-            } else {
-              var result0 = null;;
-            };
-          };
+            if (result0 === null) {
+              pos = pos0;
+            }
+          }
         }
-        reportMatchFailures = savedReportMatchFailures;
-        if (reportMatchFailures && result0 === null) {
+        reportFailures--;
+        if (reportFailures === 0 && result0 === null) {
           matchFailed("inline");
         }
         
@@ -2463,43 +2360,31 @@ var parser = (function(){
       }
       
       function parse_inline_part() {
-        var cacheKey = 'inline_part@' + pos;
+        var cacheKey = "inline_part@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
+        var result0;
+        var pos0;
         
-        var result5 = parse_special();
-        if (result5 !== null) {
-          var result0 = result5;
-        } else {
-          var result4 = parse_reference();
-          if (result4 !== null) {
-            var result0 = result4;
-          } else {
-            var savedPos0 = pos;
-            var result2 = parse_literal();
-            var result3 = result2 !== null
-              ? (function(l) { return ["buffer", l] })(result2)
-              : null;
-            if (result3 !== null) {
-              var result1 = result3;
-            } else {
-              var result1 = null;
-              pos = savedPos0;
+        result0 = parse_special();
+        if (result0 === null) {
+          result0 = parse_reference();
+          if (result0 === null) {
+            pos0 = pos;
+            result0 = parse_literal();
+            if (result0 !== null) {
+              result0 = (function(offset, l) { return ["buffer", l] })(pos0, result0);
             }
-            if (result1 !== null) {
-              var result0 = result1;
-            } else {
-              var result0 = null;;
-            };
-          };
+            if (result0 === null) {
+              pos = pos0;
+            }
+          }
         }
         
-        
-        
         cache[cacheKey] = {
           nextPos: pos,
           result:  result0
@@ -2508,221 +2393,198 @@ var parser = (function(){
       }
       
       function parse_buffer() {
-        var cacheKey = 'buffer@' + pos;
+        var cacheKey = "buffer@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
-        var savedReportMatchFailures = reportMatchFailures;
-        reportMatchFailures = false;
-        var savedPos6 = pos;
-        var savedPos7 = pos;
-        var result17 = parse_eol();
-        if (result17 !== null) {
-          var result18 = [];
-          var result19 = parse_ws();
-          while (result19 !== null) {
-            result18.push(result19);
-            var result19 = parse_ws();
-          }
-          if (result18 !== null) {
-            var result15 = [result17, result18];
+        var result0, result1, result2, result3, result4;
+        var pos0, pos1, pos2, pos3;
+        
+        reportFailures++;
+        pos0 = pos;
+        pos1 = pos;
+        result0 = parse_eol();
+        if (result0 !== null) {
+          result1 = [];
+          result2 = parse_ws();
+          while (result2 !== null) {
+            result1.push(result2);
+            result2 = parse_ws();
+          }
+          if (result1 !== null) {
+            result0 = [result0, result1];
           } else {
-            var result15 = null;
-            pos = savedPos7;
+            result0 = null;
+            pos = pos1;
           }
         } else {
-          var result15 = null;
-          pos = savedPos7;
-        }
-        var result16 = result15 !== null
-          ? (function(e, w) { return ["format", e, w.join('')] })(result15[0], result15[1])
-          : null;
-        if (result16 !== null) {
-          var result14 = result16;
-        } else {
-          var result14 = null;
-          pos = savedPos6;
+          result0 = null;
+          pos = pos1;
         }
-        if (result14 !== null) {
-          var result0 = result14;
-        } else {
-          var savedPos0 = pos;
-          var savedPos1 = pos;
-          var savedPos2 = pos;
-          var savedPos5 = pos;
-          var savedReportMatchFailuresVar2 = reportMatchFailures;
-          reportMatchFailures = false;
-          var result13 = parse_tag();
-          reportMatchFailures = savedReportMatchFailuresVar2;
-          if (result13 === null) {
-            var result7 = '';
+        if (result0 !== null) {
+          result0 = (function(offset, e, w) { return ["format", e, w.join('')] })(pos0, result0[0], result0[1]);
+        }
+        if (result0 === null) {
+          pos = pos0;
+        }
+        if (result0 === null) {
+          pos0 = pos;
+          pos1 = pos;
+          pos2 = pos;
+          pos3 = pos;
+          reportFailures++;
+          result1 = parse_tag();
+          reportFailures--;
+          if (result1 === null) {
+            result1 = "";
           } else {
-            var result7 = null;
-            pos = savedPos5;
-          }
-          if (result7 !== null) {
-            var savedPos4 = pos;
-            var savedReportMatchFailuresVar1 = reportMatchFailures;
-            reportMatchFailures = false;
-            var result12 = parse_eol();
-            reportMatchFailures = savedReportMatchFailuresVar1;
-            if (result12 === null) {
-              var result8 = '';
+            result1 = null;
+            pos = pos3;
+          }
+          if (result1 !== null) {
+            pos3 = pos;
+            reportFailures++;
+            result2 = parse_eol();
+            reportFailures--;
+            if (result2 === null) {
+              result2 = "";
             } else {
-              var result8 = null;
-              pos = savedPos4;
-            }
-            if (result8 !== null) {
-              var savedPos3 = pos;
-              var savedReportMatchFailuresVar0 = reportMatchFailures;
-              reportMatchFailures = false;
-              var result11 = parse_comment();
-              reportMatchFailures = savedReportMatchFailuresVar0;
-              if (result11 === null) {
-                var result9 = '';
+              result2 = null;
+              pos = pos3;
+            }
+            if (result2 !== null) {
+              pos3 = pos;
+              reportFailures++;
+              result3 = parse_comment();
+              reportFailures--;
+              if (result3 === null) {
+                result3 = "";
               } else {
-                var result9 = null;
-                pos = savedPos3;
+                result3 = null;
+                pos = pos3;
               }
-              if (result9 !== null) {
+              if (result3 !== null) {
                 if (input.length > pos) {
-                  var result10 = input.charAt(pos);
+                  result4 = input.charAt(pos);
                   pos++;
                 } else {
-                  var result10 = null;
-                  if (reportMatchFailures) {
-                    matchFailed('any character');
+                  result4 = null;
+                  if (reportFailures === 0) {
+                    matchFailed("any character");
                   }
                 }
-                if (result10 !== null) {
-                  var result5 = [result7, result8, result9, result10];
+                if (result4 !== null) {
+                  result1 = [result1, result2, result3, result4];
                 } else {
-                  var result5 = null;
-                  pos = savedPos2;
+                  result1 = null;
+                  pos = pos2;
                 }
               } else {
-                var result5 = null;
-                pos = savedPos2;
+                result1 = null;
+                pos = pos2;
               }
             } else {
-              var result5 = null;
-              pos = savedPos2;
+              result1 = null;
+              pos = pos2;
             }
           } else {
-            var result5 = null;
-            pos = savedPos2;
-          }
-          var result6 = result5 !== null
-            ? (function(c) {return c})(result5[3])
-            : null;
-          if (result6 !== null) {
-            var result4 = result6;
-          } else {
-            var result4 = null;
-            pos = savedPos1;
-          }
-          if (result4 !== null) {
-            var result2 = [];
-            while (result4 !== null) {
-              result2.push(result4);
-              var savedPos1 = pos;
-              var savedPos2 = pos;
-              var savedPos5 = pos;
-              var savedReportMatchFailuresVar2 = reportMatchFailures;
-              reportMatchFailures = false;
-              var result13 = parse_tag();
-              reportMatchFailures = savedReportMatchFailuresVar2;
-              if (result13 === null) {
-                var result7 = '';
+            result1 = null;
+            pos = pos2;
+          }
+          if (result1 !== null) {
+            result1 = (function(offset, c) {return c})(pos1, result1[3]);
+          }
+          if (result1 === null) {
+            pos = pos1;
+          }
+          if (result1 !== null) {
+            result0 = [];
+            while (result1 !== null) {
+              result0.push(result1);
+              pos1 = pos;
+              pos2 = pos;
+              pos3 = pos;
+              reportFailures++;
+              result1 = parse_tag();
+              reportFailures--;
+              if (result1 === null) {
+                result1 = "";
               } else {
-                var result7 = null;
-                pos = savedPos5;
+                result1 = null;
+                pos = pos3;
               }
-              if (result7 !== null) {
-                var savedPos4 = pos;
-                var savedReportMatchFailuresVar1 = reportMatchFailures;
-                reportMatchFailures = false;
-                var result12 = parse_eol();
-                reportMatchFailures = savedReportMatchFailuresVar1;
-                if (result12 === null) {
-                  var result8 = '';
+              if (result1 !== null) {
+                pos3 = pos;
+                reportFailures++;
+                result2 = parse_eol();
+                reportFailures--;
+                if (result2 === null) {
+                  result2 = "";
                 } else {
-                  var result8 = null;
-                  pos = savedPos4;
+                  result2 = null;
+                  pos = pos3;
                 }
-                if (result8 !== null) {
-                  var savedPos3 = pos;
-                  var savedReportMatchFailuresVar0 = reportMatchFailures;
-                  reportMatchFailures = false;
-                  var result11 = parse_comment();
-                  reportMatchFailures = savedReportMatchFailuresVar0;
-                  if (result11 === null) {
-                    var result9 = '';
+                if (result2 !== null) {
+                  pos3 = pos;
+                  reportFailures++;
+                  result3 = parse_comment();
+                  reportFailures--;
+                  if (result3 === null) {
+                    result3 = "";
                   } else {
-                    var result9 = null;
-                    pos = savedPos3;
+                    result3 = null;
+                    pos = pos3;
                   }
-                  if (result9 !== null) {
+                  if (result3 !== null) {
                     if (input.length > pos) {
-                      var result10 = input.charAt(pos);
+                      result4 = input.charAt(pos);
                       pos++;
                     } else {
-                      var result10 = null;
-                      if (reportMatchFailures) {
-                        matchFailed('any character');
+                      result4 = null;
+                      if (reportFailures === 0) {
+                        matchFailed("any character");
                       }
                     }
-                    if (result10 !== null) {
-                      var result5 = [result7, result8, result9, result10];
+                    if (result4 !== null) {
+                      result1 = [result1, result2, result3, result4];
                     } else {
-                      var result5 = null;
-                      pos = savedPos2;
+                      result1 = null;
+                      pos = pos2;
                     }
                   } else {
-                    var result5 = null;
-                    pos = savedPos2;
+                    result1 = null;
+                    pos = pos2;
                   }
                 } else {
-                  var result5 = null;
-                  pos = savedPos2;
+                  result1 = null;
+                  pos = pos2;
                 }
               } else {
-                var result5 = null;
-                pos = savedPos2;
+                result1 = null;
+                pos = pos2;
               }
-              var result6 = result5 !== null
-                ? (function(c) {return c})(result5[3])
-                : null;
-              if (result6 !== null) {
-                var result4 = result6;
-              } else {
-                var result4 = null;
-                pos = savedPos1;
+              if (result1 !== null) {
+                result1 = (function(offset, c) {return c})(pos1, result1[3]);
+              }
+              if (result1 === null) {
+                pos = pos1;
               }
             }
           } else {
-            var result2 = null;
+            result0 = null;
           }
-          var result3 = result2 !== null
-            ? (function(b) { return ["buffer", b.join('')] })(result2)
-            : null;
-          if (result3 !== null) {
-            var result1 = result3;
-          } else {
-            var result1 = null;
-            pos = savedPos0;
+          if (result0 !== null) {
+            result0 = (function(offset, b) { return ["buffer", b.join('')] })(pos0, result0);
+          }
+          if (result0 === null) {
+            pos = pos0;
           }
-          if (result1 !== null) {
-            var result0 = result1;
-          } else {
-            var result0 = null;;
-          };
         }
-        reportMatchFailures = savedReportMatchFailures;
-        if (reportMatchFailures && result0 === null) {
+        reportFailures--;
+        if (reportFailures === 0 && result0 === null) {
           matchFailed("buffer");
         }
         
@@ -2734,171 +2596,146 @@ var parser = (function(){
       }
       
       function parse_literal() {
-        var cacheKey = 'literal@' + pos;
+        var cacheKey = "literal@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
-        var savedReportMatchFailures = reportMatchFailures;
-        reportMatchFailures = false;
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var savedPos2 = pos;
-        var savedPos4 = pos;
-        var savedReportMatchFailuresVar1 = reportMatchFailures;
-        reportMatchFailures = false;
-        var result12 = parse_tag();
-        reportMatchFailures = savedReportMatchFailuresVar1;
-        if (result12 === null) {
-          var result6 = '';
-        } else {
-          var result6 = null;
-          pos = savedPos4;
-        }
-        if (result6 !== null) {
-          var savedPos3 = pos;
-          var savedReportMatchFailuresVar0 = reportMatchFailures;
-          reportMatchFailures = false;
-          var result11 = parse_eol();
-          reportMatchFailures = savedReportMatchFailuresVar0;
-          if (result11 === null) {
-            var result7 = '';
-          } else {
-            var result7 = null;
-            pos = savedPos3;
-          }
-          if (result7 !== null) {
-            var result10 = parse_esc();
-            if (result10 !== null) {
-              var result8 = result10;
-            } else {
-              if (input.substr(pos).match(/^[^"]/) !== null) {
-                var result9 = input.charAt(pos);
+        var result0, result1, result2, result3;
+        var pos0, pos1, pos2, pos3;
+        
+        reportFailures++;
+        pos0 = pos;
+        pos1 = pos;
+        pos2 = pos;
+        pos3 = pos;
+        reportFailures++;
+        result1 = parse_tag();
+        reportFailures--;
+        if (result1 === null) {
+          result1 = "";
+        } else {
+          result1 = null;
+          pos = pos3;
+        }
+        if (result1 !== null) {
+          pos3 = pos;
+          reportFailures++;
+          result2 = parse_eol();
+          reportFailures--;
+          if (result2 === null) {
+            result2 = "";
+          } else {
+            result2 = null;
+            pos = pos3;
+          }
+          if (result2 !== null) {
+            result3 = parse_esc();
+            if (result3 === null) {
+              if (/^[^"]/.test(input.charAt(pos))) {
+                result3 = input.charAt(pos);
                 pos++;
               } else {
-                var result9 = null;
-                if (reportMatchFailures) {
+                result3 = null;
+                if (reportFailures === 0) {
                   matchFailed("[^\"]");
                 }
               }
-              if (result9 !== null) {
-                var result8 = result9;
-              } else {
-                var result8 = null;;
-              };
             }
-            if (result8 !== null) {
-              var result4 = [result6, result7, result8];
+            if (result3 !== null) {
+              result1 = [result1, result2, result3];
             } else {
-              var result4 = null;
-              pos = savedPos2;
+              result1 = null;
+              pos = pos2;
             }
           } else {
-            var result4 = null;
-            pos = savedPos2;
+            result1 = null;
+            pos = pos2;
           }
         } else {
-          var result4 = null;
-          pos = savedPos2;
-        }
-        var result5 = result4 !== null
-          ? (function(c) {return c})(result4[2])
-          : null;
-        if (result5 !== null) {
-          var result3 = result5;
-        } else {
-          var result3 = null;
-          pos = savedPos1;
-        }
-        if (result3 !== null) {
-          var result1 = [];
-          while (result3 !== null) {
-            result1.push(result3);
-            var savedPos1 = pos;
-            var savedPos2 = pos;
-            var savedPos4 = pos;
-            var savedReportMatchFailuresVar1 = reportMatchFailures;
-            reportMatchFailures = false;
-            var result12 = parse_tag();
-            reportMatchFailures = savedReportMatchFailuresVar1;
-            if (result12 === null) {
-              var result6 = '';
+          result1 = null;
+          pos = pos2;
+        }
+        if (result1 !== null) {
+          result1 = (function(offset, c) {return c})(pos1, result1[2]);
+        }
+        if (result1 === null) {
+          pos = pos1;
+        }
+        if (result1 !== null) {
+          result0 = [];
+          while (result1 !== null) {
+            result0.push(result1);
+            pos1 = pos;
+            pos2 = pos;
+            pos3 = pos;
+            reportFailures++;
+            result1 = parse_tag();
+            reportFailures--;
+            if (result1 === null) {
+              result1 = "";
             } else {
-              var result6 = null;
-              pos = savedPos4;
-            }
-            if (result6 !== null) {
-              var savedPos3 = pos;
-              var savedReportMatchFailuresVar0 = reportMatchFailures;
-              reportMatchFailures = false;
-              var result11 = parse_eol();
-              reportMatchFailures = savedReportMatchFailuresVar0;
-              if (result11 === null) {
-                var result7 = '';
+              result1 = null;
+              pos = pos3;
+            }
+            if (result1 !== null) {
+              pos3 = pos;
+              reportFailures++;
+              result2 = parse_eol();
+              reportFailures--;
+              if (result2 === null) {
+                result2 = "";
               } else {
-                var result7 = null;
-                pos = savedPos3;
+                result2 = null;
+                pos = pos3;
               }
-              if (result7 !== null) {
-                var result10 = parse_esc();
-                if (result10 !== null) {
-                  var result8 = result10;
-                } else {
-                  if (input.substr(pos).match(/^[^"]/) !== null) {
-                    var result9 = input.charAt(pos);
+              if (result2 !== null) {
+                result3 = parse_esc();
+                if (result3 === null) {
+                  if (/^[^"]/.test(input.charAt(pos))) {
+                    result3 = input.charAt(pos);
                     pos++;
                   } else {
-                    var result9 = null;
-                    if (reportMatchFailures) {
+                    result3 = null;
+                    if (reportFailures === 0) {
                       matchFailed("[^\"]");
                     }
                   }
-                  if (result9 !== null) {
-                    var result8 = result9;
-                  } else {
-                    var result8 = null;;
-                  };
                 }
-                if (result8 !== null) {
-                  var result4 = [result6, result7, result8];
+                if (result3 !== null) {
+                  result1 = [result1, result2, result3];
                 } else {
-                  var result4 = null;
-                  pos = savedPos2;
+                  result1 = null;
+                  pos = pos2;
                 }
               } else {
-                var result4 = null;
-                pos = savedPos2;
+                result1 = null;
+                pos = pos2;
               }
             } else {
-              var result4 = null;
-              pos = savedPos2;
-            }
-            var result5 = result4 !== null
-              ? (function(c) {return c})(result4[2])
-              : null;
-            if (result5 !== null) {
-              var result3 = result5;
-            } else {
-              var result3 = null;
-              pos = savedPos1;
+              result1 = null;
+              pos = pos2;
+            }
+            if (result1 !== null) {
+              result1 = (function(offset, c) {return c})(pos1, result1[2]);
+            }
+            if (result1 === null) {
+              pos = pos1;
             }
           }
         } else {
-          var result1 = null;
+          result0 = null;
         }
-        var result2 = result1 !== null
-          ? (function(b) { return b.join('') })(result1)
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
+        if (result0 !== null) {
+          result0 = (function(offset, b) { return b.join('') })(pos0, result0);
+        }
+        if (result0 === null) {
+          pos = pos0;
         }
-        reportMatchFailures = savedReportMatchFailures;
-        if (reportMatchFailures && result0 === null) {
+        reportFailures--;
+        if (reportFailures === 0 && result0 === null) {
           matchFailed("literal");
         }
         
@@ -2910,35 +2747,32 @@ var parser = (function(){
       }
       
       function parse_esc() {
-        var cacheKey = 'esc@' + pos;
+        var cacheKey = "esc@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
+        var result0;
+        var pos0;
         
-        var savedPos0 = pos;
+        pos0 = pos;
         if (input.substr(pos, 2) === "\\\"") {
-          var result1 = "\\\"";
+          result0 = "\\\"";
           pos += 2;
         } else {
-          var result1 = null;
-          if (reportMatchFailures) {
+          result0 = null;
+          if (reportFailures === 0) {
             matchFailed("\"\\\\\\\"\"");
           }
         }
-        var result2 = result1 !== null
-          ? (function() { return '"' })()
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
+        if (result0 !== null) {
+          result0 = (function(offset) { return '"' })(pos0);
+        }
+        if (result0 === null) {
+          pos = pos0;
         }
-        
-        
         
         cache[cacheKey] = {
           nextPos: pos,
@@ -2948,166 +2782,157 @@ var parser = (function(){
       }
       
       function parse_comment() {
-        var cacheKey = 'comment@' + pos;
+        var cacheKey = "comment@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
-        var savedReportMatchFailures = reportMatchFailures;
-        reportMatchFailures = false;
-        var savedPos0 = pos;
-        var savedPos1 = pos;
+        var result0, result1, result2, result3;
+        var pos0, pos1, pos2, pos3, pos4;
+        
+        reportFailures++;
+        pos0 = pos;
+        pos1 = pos;
         if (input.substr(pos, 2) === "{!") {
-          var result3 = "{!";
+          result0 = "{!";
           pos += 2;
         } else {
-          var result3 = null;
-          if (reportMatchFailures) {
+          result0 = null;
+          if (reportFailures === 0) {
             matchFailed("\"{!\"");
           }
         }
-        if (result3 !== null) {
-          var result4 = [];
-          var savedPos2 = pos;
-          var savedPos3 = pos;
-          var savedPos4 = pos;
-          var savedReportMatchFailuresVar0 = reportMatchFailures;
-          reportMatchFailures = false;
+        if (result0 !== null) {
+          result1 = [];
+          pos2 = pos;
+          pos3 = pos;
+          pos4 = pos;
+          reportFailures++;
           if (input.substr(pos, 2) === "!}") {
-            var result11 = "!}";
+            result2 = "!}";
             pos += 2;
           } else {
-            var result11 = null;
-            if (reportMatchFailures) {
+            result2 = null;
+            if (reportFailures === 0) {
               matchFailed("\"!}\"");
             }
           }
-          reportMatchFailures = savedReportMatchFailuresVar0;
-          if (result11 === null) {
-            var result9 = '';
+          reportFailures--;
+          if (result2 === null) {
+            result2 = "";
           } else {
-            var result9 = null;
-            pos = savedPos4;
+            result2 = null;
+            pos = pos4;
           }
-          if (result9 !== null) {
+          if (result2 !== null) {
             if (input.length > pos) {
-              var result10 = input.charAt(pos);
+              result3 = input.charAt(pos);
               pos++;
             } else {
-              var result10 = null;
-              if (reportMatchFailures) {
-                matchFailed('any character');
+              result3 = null;
+              if (reportFailures === 0) {
+                matchFailed("any character");
               }
             }
-            if (result10 !== null) {
-              var result7 = [result9, result10];
+            if (result3 !== null) {
+              result2 = [result2, result3];
             } else {
-              var result7 = null;
-              pos = savedPos3;
+              result2 = null;
+              pos = pos3;
             }
           } else {
-            var result7 = null;
-            pos = savedPos3;
-          }
-          var result8 = result7 !== null
-            ? (function(c) {return c})(result7[1])
-            : null;
-          if (result8 !== null) {
-            var result6 = result8;
-          } else {
-            var result6 = null;
-            pos = savedPos2;
-          }
-          while (result6 !== null) {
-            result4.push(result6);
-            var savedPos2 = pos;
-            var savedPos3 = pos;
-            var savedPos4 = pos;
-            var savedReportMatchFailuresVar0 = reportMatchFailures;
-            reportMatchFailures = false;
+            result2 = null;
+            pos = pos3;
+          }
+          if (result2 !== null) {
+            result2 = (function(offset, c) {return c})(pos2, result2[1]);
+          }
+          if (result2 === null) {
+            pos = pos2;
+          }
+          while (result2 !== null) {
+            result1.push(result2);
+            pos2 = pos;
+            pos3 = pos;
+            pos4 = pos;
+            reportFailures++;
             if (input.substr(pos, 2) === "!}") {
-              var result11 = "!}";
+              result2 = "!}";
               pos += 2;
             } else {
-              var result11 = null;
-              if (reportMatchFailures) {
+              result2 = null;
+              if (reportFailures === 0) {
                 matchFailed("\"!}\"");
               }
             }
-            reportMatchFailures = savedReportMatchFailuresVar0;
-            if (result11 === null) {
-              var result9 = '';
+            reportFailures--;
+            if (result2 === null) {
+              result2 = "";
             } else {
-              var result9 = null;
-              pos = savedPos4;
+              result2 = null;
+              pos = pos4;
             }
-            if (result9 !== null) {
+            if (result2 !== null) {
               if (input.length > pos) {
-                var result10 = input.charAt(pos);
+                result3 = input.charAt(pos);
                 pos++;
               } else {
-                var result10 = null;
-                if (reportMatchFailures) {
-                  matchFailed('any character');
+                result3 = null;
+                if (reportFailures === 0) {
+                  matchFailed("any character");
                 }
               }
-              if (result10 !== null) {
-                var result7 = [result9, result10];
+              if (result3 !== null) {
+                result2 = [result2, result3];
               } else {
-                var result7 = null;
-                pos = savedPos3;
+                result2 = null;
+                pos = pos3;
               }
             } else {
-              var result7 = null;
-              pos = savedPos3;
-            }
-            var result8 = result7 !== null
-              ? (function(c) {return c})(result7[1])
-              : null;
-            if (result8 !== null) {
-              var result6 = result8;
-            } else {
-              var result6 = null;
-              pos = savedPos2;
+              result2 = null;
+              pos = pos3;
+            }
+            if (result2 !== null) {
+              result2 = (function(offset, c) {return c})(pos2, result2[1]);
+            }
+            if (result2 === null) {
+              pos = pos2;
             }
           }
-          if (result4 !== null) {
+          if (result1 !== null) {
             if (input.substr(pos, 2) === "!}") {
-              var result5 = "!}";
+              result2 = "!}";
               pos += 2;
             } else {
-              var result5 = null;
-              if (reportMatchFailures) {
+              result2 = null;
+              if (reportFailures === 0) {
                 matchFailed("\"!}\"");
               }
             }
-            if (result5 !== null) {
-              var result1 = [result3, result4, result5];
+            if (result2 !== null) {
+              result0 = [result0, result1, result2];
             } else {
-              var result1 = null;
-              pos = savedPos1;
+              result0 = null;
+              pos = pos1;
             }
           } else {
-            var result1 = null;
-            pos = savedPos1;
+            result0 = null;
+            pos = pos1;
           }
         } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(c) { return ["comment", c.join('')] })(result1[1])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
+          result0 = null;
+          pos = pos1;
+        }
+        if (result0 !== null) {
+          result0 = (function(offset, c) { return ["comment", c.join('')] })(pos0, result0[1]);
+        }
+        if (result0 === null) {
+          pos = pos0;
         }
-        reportMatchFailures = savedReportMatchFailures;
-        if (reportMatchFailures && result0 === null) {
+        reportFailures--;
+        if (reportFailures === 0 && result0 === null) {
           matchFailed("comment");
         }
         
@@ -3119,164 +2944,153 @@ var parser = (function(){
       }
       
       function parse_tag() {
-        var cacheKey = 'tag@' + pos;
+        var cacheKey = "tag@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
+        var result0, result1, result2, result3, result4, result5;
+        var pos0, pos1, pos2;
         
-        var savedPos0 = pos;
-        var result3 = parse_ld();
-        if (result3 !== null) {
-          if (input.substr(pos).match(/^[#?^><+%:@\/~%]/) !== null) {
-            var result4 = input.charAt(pos);
+        pos0 = pos;
+        result0 = parse_ld();
+        if (result0 !== null) {
+          if (/^[#?^><+%:@\/~%]/.test(input.charAt(pos))) {
+            result1 = input.charAt(pos);
             pos++;
           } else {
-            var result4 = null;
-            if (reportMatchFailures) {
+            result1 = null;
+            if (reportFailures === 0) {
               matchFailed("[#?^><+%:@\\/~%]");
             }
           }
-          if (result4 !== null) {
-            var savedPos1 = pos;
-            var savedPos3 = pos;
-            var savedReportMatchFailuresVar1 = reportMatchFailures;
-            reportMatchFailures = false;
-            var result12 = parse_rd();
-            reportMatchFailures = savedReportMatchFailuresVar1;
-            if (result12 === null) {
-              var result8 = '';
+          if (result1 !== null) {
+            pos1 = pos;
+            pos2 = pos;
+            reportFailures++;
+            result3 = parse_rd();
+            reportFailures--;
+            if (result3 === null) {
+              result3 = "";
             } else {
-              var result8 = null;
-              pos = savedPos3;
-            }
-            if (result8 !== null) {
-              var savedPos2 = pos;
-              var savedReportMatchFailuresVar0 = reportMatchFailures;
-              reportMatchFailures = false;
-              var result11 = parse_eol();
-              reportMatchFailures = savedReportMatchFailuresVar0;
-              if (result11 === null) {
-                var result9 = '';
+              result3 = null;
+              pos = pos2;
+            }
+            if (result3 !== null) {
+              pos2 = pos;
+              reportFailures++;
+              result4 = parse_eol();
+              reportFailures--;
+              if (result4 === null) {
+                result4 = "";
               } else {
-                var result9 = null;
-                pos = savedPos2;
+                result4 = null;
+                pos = pos2;
               }
-              if (result9 !== null) {
+              if (result4 !== null) {
                 if (input.length > pos) {
-                  var result10 = input.charAt(pos);
+                  result5 = input.charAt(pos);
                   pos++;
                 } else {
-                  var result10 = null;
-                  if (reportMatchFailures) {
-                    matchFailed('any character');
+                  result5 = null;
+                  if (reportFailures === 0) {
+                    matchFailed("any character");
                   }
                 }
-                if (result10 !== null) {
-                  var result7 = [result8, result9, result10];
+                if (result5 !== null) {
+                  result3 = [result3, result4, result5];
                 } else {
-                  var result7 = null;
-                  pos = savedPos1;
+                  result3 = null;
+                  pos = pos1;
                 }
               } else {
-                var result7 = null;
-                pos = savedPos1;
+                result3 = null;
+                pos = pos1;
               }
             } else {
-              var result7 = null;
-              pos = savedPos1;
-            }
-            if (result7 !== null) {
-              var result5 = [];
-              while (result7 !== null) {
-                result5.push(result7);
-                var savedPos1 = pos;
-                var savedPos3 = pos;
-                var savedReportMatchFailuresVar1 = reportMatchFailures;
-                reportMatchFailures = false;
-                var result12 = parse_rd();
-                reportMatchFailures = savedReportMatchFailuresVar1;
-                if (result12 === null) {
-                  var result8 = '';
+              result3 = null;
+              pos = pos1;
+            }
+            if (result3 !== null) {
+              result2 = [];
+              while (result3 !== null) {
+                result2.push(result3);
+                pos1 = pos;
+                pos2 = pos;
+                reportFailures++;
+                result3 = parse_rd();
+                reportFailures--;
+                if (result3 === null) {
+                  result3 = "";
                 } else {
-                  var result8 = null;
-                  pos = savedPos3;
+                  result3 = null;
+                  pos = pos2;
                 }
-                if (result8 !== null) {
-                  var savedPos2 = pos;
-                  var savedReportMatchFailuresVar0 = reportMatchFailures;
-                  reportMatchFailures = false;
-                  var result11 = parse_eol();
-                  reportMatchFailures = savedReportMatchFailuresVar0;
-                  if (result11 === null) {
-                    var result9 = '';
+                if (result3 !== null) {
+                  pos2 = pos;
+                  reportFailures++;
+                  result4 = parse_eol();
+                  reportFailures--;
+                  if (result4 === null) {
+                    result4 = "";
                   } else {
-                    var result9 = null;
-                    pos = savedPos2;
+                    result4 = null;
+                    pos = pos2;
                   }
-                  if (result9 !== null) {
+                  if (result4 !== null) {
                     if (input.length > pos) {
-                      var result10 = input.charAt(pos);
+                      result5 = input.charAt(pos);
                       pos++;
                     } else {
-                      var result10 = null;
-                      if (reportMatchFailures) {
-                        matchFailed('any character');
+                      result5 = null;
+                      if (reportFailures === 0) {
+                        matchFailed("any character");
                       }
                     }
-                    if (result10 !== null) {
-                      var result7 = [result8, result9, result10];
+                    if (result5 !== null) {
+                      result3 = [result3, result4, result5];
                     } else {
-                      var result7 = null;
-                      pos = savedPos1;
+                      result3 = null;
+                      pos = pos1;
                     }
                   } else {
-                    var result7 = null;
-                    pos = savedPos1;
+                    result3 = null;
+                    pos = pos1;
                   }
                 } else {
-                  var result7 = null;
-                  pos = savedPos1;
+                  result3 = null;
+                  pos = pos1;
                 }
               }
             } else {
-              var result5 = null;
+              result2 = null;
             }
-            if (result5 !== null) {
-              var result6 = parse_rd();
-              if (result6 !== null) {
-                var result2 = [result3, result4, result5, result6];
+            if (result2 !== null) {
+              result3 = parse_rd();
+              if (result3 !== null) {
+                result0 = [result0, result1, result2, result3];
               } else {
-                var result2 = null;
-                pos = savedPos0;
+                result0 = null;
+                pos = pos0;
               }
             } else {
-              var result2 = null;
-              pos = savedPos0;
+              result0 = null;
+              pos = pos0;
             }
           } else {
-            var result2 = null;
-            pos = savedPos0;
+            result0 = null;
+            pos = pos0;
           }
         } else {
-          var result2 = null;
-          pos = savedPos0;
+          result0 = null;
+          pos = pos0;
         }
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result1 = parse_reference();
-          if (result1 !== null) {
-            var result0 = result1;
-          } else {
-            var result0 = null;;
-          };
+        if (result0 === null) {
+          result0 = parse_reference();
         }
         
-        
-        
         cache[cacheKey] = {
           nextPos: pos,
           result:  result0
@@ -3285,26 +3099,25 @@ var parser = (function(){
       }
       
       function parse_ld() {
-        var cacheKey = 'ld@' + pos;
+        var cacheKey = "ld@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
+        var result0;
         
-        if (input.substr(pos, 1) === "{") {
-          var result0 = "{";
-          pos += 1;
+        if (input.charCodeAt(pos) === 123) {
+          result0 = "{";
+          pos++;
         } else {
-          var result0 = null;
-          if (reportMatchFailures) {
+          result0 = null;
+          if (reportFailures === 0) {
             matchFailed("\"{\"");
           }
         }
         
-        
-        
         cache[cacheKey] = {
           nextPos: pos,
           result:  result0
@@ -3313,26 +3126,25 @@ var parser = (function(){
       }
       
       function parse_rd() {
-        var cacheKey = 'rd@' + pos;
+        var cacheKey = "rd@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
+        var result0;
         
-        if (input.substr(pos, 1) === "}") {
-          var result0 = "}";
-          pos += 1;
+        if (input.charCodeAt(pos) === 125) {
+          result0 = "}";
+          pos++;
         } else {
-          var result0 = null;
-          if (reportMatchFailures) {
+          result0 = null;
+          if (reportFailures === 0) {
             matchFailed("\"}\"");
           }
         }
         
-        
-        
         cache[cacheKey] = {
           nextPos: pos,
           result:  result0
@@ -3341,83 +3153,69 @@ var parser = (function(){
       }
       
       function parse_eol() {
-        var cacheKey = 'eol@' + pos;
+        var cacheKey = "eol@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
+        var result0;
         
-        if (input.substr(pos, 1) === "\n") {
-          var result5 = "\n";
-          pos += 1;
+        if (input.charCodeAt(pos) === 10) {
+          result0 = "\n";
+          pos++;
         } else {
-          var result5 = null;
-          if (reportMatchFailures) {
+          result0 = null;
+          if (reportFailures === 0) {
             matchFailed("\"\\n\"");
           }
         }
-        if (result5 !== null) {
-          var result0 = result5;
-        } else {
+        if (result0 === null) {
           if (input.substr(pos, 2) === "\r\n") {
-            var result4 = "\r\n";
+            result0 = "\r\n";
             pos += 2;
           } else {
-            var result4 = null;
-            if (reportMatchFailures) {
+            result0 = null;
+            if (reportFailures === 0) {
               matchFailed("\"\\r\\n\"");
             }
           }
-          if (result4 !== null) {
-            var result0 = result4;
-          } else {
-            if (input.substr(pos, 1) === "\r") {
-              var result3 = "\r";
-              pos += 1;
+          if (result0 === null) {
+            if (input.charCodeAt(pos) === 13) {
+              result0 = "\r";
+              pos++;
             } else {
-              var result3 = null;
-              if (reportMatchFailures) {
+              result0 = null;
+              if (reportFailures === 0) {
                 matchFailed("\"\\r\"");
               }
             }
-            if (result3 !== null) {
-              var result0 = result3;
-            } else {
-              if (input.substr(pos, 1) === "\u2028") {
-                var result2 = "\u2028";
-                pos += 1;
+            if (result0 === null) {
+              if (input.charCodeAt(pos) === 8232) {
+                result0 = "\u2028";
+                pos++;
               } else {
-                var result2 = null;
-                if (reportMatchFailures) {
+                result0 = null;
+                if (reportFailures === 0) {
                   matchFailed("\"\\u2028\"");
                 }
               }
-              if (result2 !== null) {
-                var result0 = result2;
-              } else {
-                if (input.substr(pos, 1) === "\u2029") {
-                  var result1 = "\u2029";
-                  pos += 1;
+              if (result0 === null) {
+                if (input.charCodeAt(pos) === 8233) {
+                  result0 = "\u2029";
+                  pos++;
                 } else {
-                  var result1 = null;
-                  if (reportMatchFailures) {
+                  result0 = null;
+                  if (reportFailures === 0) {
                     matchFailed("\"\\u2029\"");
                   }
                 }
-                if (result1 !== null) {
-                  var result0 = result1;
-                } else {
-                  var result0 = null;;
-                };
-              };
-            };
-          };
+              }
+            }
+          }
         }
         
-        
-        
         cache[cacheKey] = {
           nextPos: pos,
           result:  result0
@@ -3426,26 +3224,25 @@ var parser = (function(){
       }
       
       function parse_ws() {
-        var cacheKey = 'ws@' + pos;
+        var cacheKey = "ws@" + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
           return cachedResult.result;
         }
         
+        var result0;
         
-        if (input.substr(pos).match(/^[	 \xA0\uFEFF]/) !== null) {
-          var result0 = input.charAt(pos);
+        if (/^[\t\x0B\f \xA0\uFEFF]/.test(input.charAt(pos))) {
+          result0 = input.charAt(pos);
           pos++;
         } else {
-          var result0 = null;
-          if (reportMatchFailures) {
-            matchFailed("[	 \\xA0\\uFEFF]");
+          result0 = null;
+          if (reportFailures === 0) {
+            matchFailed("[\\t\\x0B\\f \\xA0\\uFEFF]");
           }
         }
         
-        
-        
         cache[cacheKey] = {
           nextPos: pos,
           result:  result0
@@ -3453,38 +3250,19 @@ var parser = (function(){
         return result0;
       }
       
-      function buildErrorMessage() {
-        function buildExpected(failuresExpected) {
-          failuresExpected.sort();
-          
-          var lastFailure = null;
-          var failuresExpectedUnique = [];
-          for (var i = 0; i < failuresExpected.length; i++) {
-            if (failuresExpected[i] !== lastFailure) {
-              failuresExpectedUnique.push(failuresExpected[i]);
-              lastFailure = failuresExpected[i];
-            }
-          }
-          
-          switch (failuresExpectedUnique.length) {
-            case 0:
-              return 'end of input';
-            case 1:
-              return failuresExpectedUnique[0];
-            default:
-              return failuresExpectedUnique.slice(0, failuresExpectedUnique.length - 1).join(', ')
-                + ' or '
-                + failuresExpectedUnique[failuresExpectedUnique.length - 1];
-          }
-        }
-        
-        var expected = buildExpected(rightmostMatchFailuresExpected);
-        var actualPos = Math.max(pos, rightmostMatchFailuresPos);
-        var actual = actualPos < input.length
-          ? quote(input.charAt(actualPos))
-          : 'end of input';
-        
-        return 'Expected ' + expected + ' but ' + actual + ' found.';
+      
+      function cleanupExpected(expected) {
+        expected.sort();
+        
+        var lastExpected = null;
+        var cleanExpected = [];
+        for (var i = 0; i < expected.length; i++) {
+          if (expected[i] !== lastExpected) {
+            cleanExpected.push(expected[i]);
+            lastExpected = expected[i];
+          }
+        }
+        return cleanExpected;
       }
       
       function computeErrorPosition() {
@@ -3499,13 +3277,13 @@ var parser = (function(){
         var column = 1;
         var seenCR = false;
         
-        for (var i = 0; i <  rightmostMatchFailuresPos; i++) {
+        for (var i = 0; i < Math.max(pos, rightmostFailuresPos); i++) {
           var ch = input.charAt(i);
-          if (ch === '\n') {
+          if (ch === "\n") {
             if (!seenCR) { line++; }
             column = 1;
             seenCR = false;
-          } else if (ch === '\r' | ch === '\u2028' || ch === '\u2029') {
+          } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
             line++;
             column = 1;
             seenCR = true;
@@ -3519,16 +3297,11 @@ var parser = (function(){
       }
       
       
+        function wrap(node, ck) {
+          node['text'] = input.substring(ck.split('@')[1], pos);
+          return node;
+        }
       
-    function wrap(node, ck) {
-      
-      node['text'] = input.substring(ck.split('@')[1], pos);
-      
-      return node;
-      
-    }
-      
-  
       
       var result = parseFunctions[startRule]();
       
@@ -3539,27 +3312,32 @@ var parser = (function(){
        *
        *    - |result !== null|
        *    - |pos === input.length|
-       *    - |rightmostMatchFailuresExpected| may or may not contain something
+       *    - |rightmostFailuresExpected| may or may not contain something
        *
        * 2. The parser successfully parsed only a part of the input.
        *
        *    - |result !== null|
        *    - |pos < input.length|
-       *    - |rightmostMatchFailuresExpected| may or may not contain something
+       *    - |rightmostFailuresExpected| may or may not contain something
        *
        * 3. The parser did not successfully parse any part of the input.
        *
        *   - |result === null|
        *   - |pos === 0|
-       *   - |rightmostMatchFailuresExpected| contains at least one failure
+       *   - |rightmostFailuresExpected| contains at least one failure
        *
        * All code following this comment (including called functions) must
        * handle these states.
        */
       if (result === null || pos !== input.length) {
+        var offset = Math.max(pos, rightmostFailuresPos);
+        var found = offset < input.length ? input.charAt(offset) : null;
         var errorPosition = computeErrorPosition();
+        
         throw new parser.SyntaxError(
-          buildErrorMessage(),
+          cleanupExpected(rightmostFailuresExpected),
+          found,
+          offset,
           errorPosition.line,
           errorPosition.column
         );
@@ -3574,9 +3352,33 @@ var parser = (function(){
   
   /* Thrown when a parser encounters a syntax error. */
   
-  result.SyntaxError = function(message, line, column) {
-    this.name = 'SyntaxError';
-    this.message = message;
+  result.SyntaxError = function(expected, found, offset, line, column) {
+    function buildMessage(expected, found) {
+      var expectedHumanized, foundHumanized;
+      
+      switch (expected.length) {
+        case 0:
+          expectedHumanized = "end of input";
+          break;
+        case 1:
+          expectedHumanized = expected[0];
+          break;
+        default:
+          expectedHumanized = expected.slice(0, expected.length - 1).join(", ")
+            + " or "
+            + expected[expected.length - 1];
+      }
+      
+      foundHumanized = found ? quote(found) : "end of input";
+      
+      return "Expected " + expectedHumanized + " but " + foundHumanized + " found.";
+    }
+    
+    this.name = "SyntaxError";
+    this.expected = expected;
+    this.found = found;
+    this.message = buildMessage(expected, found);
+    this.offset = offset;
     this.line = line;
     this.column = column;
   };
@@ -3588,4 +3390,4 @@ var parser = (function(){
 
 dust.parse = parser.parse;
 
-})(typeof exports !== 'undefined' ? exports : window.dust);
\ No newline at end of file
+})(typeof exports !== 'undefined' ? exports : getGlobal());
\ No newline at end of file
diff --git a/lib/compiler.js b/lib/compiler.js
index 7e471465..0d8a41c5 100644
--- a/lib/compiler.js
+++ b/lib/compiler.js
@@ -323,4 +323,4 @@ var escape = (typeof JSON === "undefined")
   ? function(str) { return "\"" + dust.escapeJs(str) + "\"" }
   : JSON.stringify;
 
-})(typeof exports !== 'undefined' ? exports : window.dust);
+})(typeof exports !== 'undefined' ? exports : getGlobal());
diff --git a/lib/dust-helpers.js b/lib/dust-helpers.js
index c0032134..ca6d472f 100644
--- a/lib/dust-helpers.js
+++ b/lib/dust-helpers.js
@@ -48,4 +48,4 @@ var helpers = {
 
 dust.helpers = helpers;
 
-})(typeof exports !== 'undefined' ? exports : window.dust);
\ No newline at end of file
+})(typeof exports !== 'undefined' ? exports : getGlobal());
\ No newline at end of file
diff --git a/lib/dust.js b/lib/dust.js
index c6e2448a..dfd26e6b 100644
--- a/lib/dust.js
+++ b/lib/dust.js
@@ -1,5 +1,11 @@
 var dust = {};
 
+function getGlobal(){	
+  return (function(){	
+    return this.dust;	
+      }).call(null);
+}
+
 (function(dust) {
 
 dust.cache = {};
@@ -501,7 +507,7 @@ dust.escapeJs = function(s) {
 
 if (typeof exports !== "undefined") {
   dust.helpers = require("./dust-helpers").helpers;
-  if (typeof process !== "undefined" && typeof window === "undefined") {
+  if (typeof process !== "undefined") {
       require('./server')(dust);
   }
   module.exports = dust;
diff --git a/lib/parser.js b/lib/parser.js
index 37e40d95..64d04f9a 100644
--- a/lib/parser.js
+++ b/lib/parser.js
@@ -2492,4 +2492,4 @@ var parser = (function(){
 
 dust.parse = parser.parse;
 
-})(typeof exports !== 'undefined' ? exports : window.dust);
\ No newline at end of file
+})(typeof exports !== 'undefined' ? exports : getGlobal());
\ No newline at end of file
diff --git a/src/build.js b/src/build.js
index 05b69193..d341d66d 100644
--- a/src/build.js
+++ b/src/build.js
@@ -10,5 +10,5 @@ var namespace = 'parser';
 fs.writeFileSync(path.join(root, 'lib', 'parser.js'), "(function(dust){\n\nvar "+namespace+" = "
   + parser.toSource().replace('this.SyntaxError', ''+namespace+'.SyntaxError') + ";\n\n"
   + "dust.parse = "+namespace+".parse;\n\n"
-  + "})(typeof exports !== 'undefined' ? exports : window.dust);"
+  + "})(typeof exports !== 'undefined' ? exports : getGlobal());"
 );
\ No newline at end of file