diff --git a/Gruntfile.js b/Gruntfile.js
index d7d286a2..08bdda47 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -192,9 +192,9 @@ module.exports = function(grunt) {
             report: 'tmp/coverage',
             thresholds: {
               lines: 82,
-              statements: 83,
-              branches: 73,
-              functions: 89
+              statements: 82,
+              branches: 70,
+              functions: 88
             }
           }
         }
@@ -305,4 +305,4 @@ module.exports = function(grunt) {
 
   //default task - full test
   grunt.registerTask('default',        ['test']);
-};
\ No newline at end of file
+};
diff --git a/archive/dust-2.3.6.tar.gz b/archive/dust-2.3.6.tar.gz
new file mode 100644
index 00000000..1ab896df
Binary files /dev/null and b/archive/dust-2.3.6.tar.gz differ
diff --git a/archive/dust-2.3.6.zip b/archive/dust-2.3.6.zip
new file mode 100644
index 00000000..05f1745d
Binary files /dev/null and b/archive/dust-2.3.6.zip differ
diff --git a/bower.json b/bower.json
index 42f9545f..1b92f8cc 100644
--- a/bower.json
+++ b/bower.json
@@ -3,7 +3,7 @@
   "version": "2.4.1",
   "main": "dist/dust-full.min.js",
   "devDependencies": {
-    "pegjs": "0.7.0"
+    "pegjs": "0.8.0"
   },
   "ignore": [
      "**/.*",
diff --git a/lib/parser.js b/lib/parser.js
index e683df63..687387c5 100644
--- a/lib/parser.js
+++ b/lib/parser.js
@@ -9,2811 +9,2650 @@
     factory(root.dust);
   }
 }(this, function(dust) {
-  var parser = (function(){
+  var parser = (function() {
   /*
-   * Generated by PEG.js 0.7.0.
+   * Generated by PEG.js 0.8.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)
-      + '"';
+
+  function peg$subclass(child, parent) {
+    function ctor() { this.constructor = child; }
+    ctor.prototype = parent.prototype;
+    child.prototype = new ctor();
   }
-  
-  var result = {
-    /*
-     * Parses the input with a generated parser. If the parsing is successfull,
-     * returns a value explicitly or implicitly specified by the grammar from
-     * which the parser was generated (see |PEG.buildParser|). If the parsing is
-     * unsuccessful, throws |PEG.parser.SyntaxError| describing the error.
-     */
-    parse: function(input, startRule) {
-      var parseFunctions = {
-        "body": parse_body,
-        "part": parse_part,
-        "section": parse_section,
-        "sec_tag_start": parse_sec_tag_start,
-        "end_tag": parse_end_tag,
-        "context": parse_context,
-        "params": parse_params,
-        "bodies": parse_bodies,
-        "reference": parse_reference,
-        "partial": parse_partial,
-        "filters": parse_filters,
-        "special": parse_special,
-        "identifier": parse_identifier,
-        "number": parse_number,
-        "float": parse_float,
-        "integer": parse_integer,
-        "path": parse_path,
-        "key": parse_key,
-        "array": parse_array,
-        "array_part": parse_array_part,
-        "inline": parse_inline,
-        "inline_part": parse_inline_part,
-        "buffer": parse_buffer,
-        "literal": parse_literal,
-        "esc": parse_esc,
-        "raw": parse_raw,
-        "comment": parse_comment,
-        "tag": parse_tag,
-        "ld": parse_ld,
-        "rd": parse_rd,
-        "lb": parse_lb,
-        "rb": parse_rb,
-        "eol": parse_eol,
-        "ws": parse_ws
-      };
-      
-      if (startRule !== undefined) {
-        if (parseFunctions[startRule] === undefined) {
-          throw new Error("Invalid rule name: " + quote(startRule) + ".");
-        }
-      } else {
-        startRule = "body";
-      }
-      
-      var pos = { offset: 0, line: 1, column: 1, seenCR: false };
-      var reportFailures = 0;
-      var rightmostFailuresPos = { offset: 0, line: 1, column: 1, seenCR: false };
-      var rightmostFailuresExpected = [];
-      
-      function padLeft(input, padding, length) {
-        var result = input;
-        
-        var padLength = length - input.length;
-        for (var i = 0; i < padLength; i++) {
-          result = padding + result;
-        }
-        
-        return result;
-      }
-      
-      function escape(ch) {
-        var charCode = ch.charCodeAt(0);
-        var escapeChar;
-        var length;
-        
-        if (charCode <= 0xFF) {
-          escapeChar = 'x';
-          length = 2;
-        } else {
-          escapeChar = 'u';
-          length = 4;
-        }
-        
-        return '\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length);
-      }
-      
-      function clone(object) {
-        var result = {};
-        for (var key in object) {
-          result[key] = object[key];
-        }
-        return result;
-      }
-      
-      function advance(pos, n) {
-        var endOffset = pos.offset + n;
-        
-        for (var offset = pos.offset; offset < endOffset; offset++) {
-          var ch = input.charAt(offset);
+
+  function SyntaxError(message, expected, found, offset, line, column) {
+    this.message  = message;
+    this.expected = expected;
+    this.found    = found;
+    this.offset   = offset;
+    this.line     = line;
+    this.column   = column;
+
+    this.name     = "SyntaxError";
+  }
+
+  peg$subclass(SyntaxError, Error);
+
+  function parse(input) {
+    var options = arguments.length > 1 ? arguments[1] : {},
+
+        peg$FAILED = {},
+
+        peg$startRuleFunctions = { start: peg$parsestart },
+        peg$startRuleFunction  = peg$parsestart,
+
+        peg$c0 = [],
+        peg$c1 = function(p) {
+            return ["body"]
+                   .concat(p)
+                   .concat([['line', line()], ['col', column()]]);
+          },
+        peg$c2 = { type: "other", description: "section" },
+        peg$c3 = peg$FAILED,
+        peg$c4 = null,
+        peg$c5 = function(t, b, e, n) {
+            if( (!n) || (t[1].text !== n.text) ) {
+              error("Expected end tag for "+t[1].text+" but it was not found.");
+            }
+            return true;
+          },
+        peg$c6 = void 0,
+        peg$c7 = function(t, b, e, n) {
+            e.push(["param", ["literal", "block"], b]);
+            t.push(e);
+            return t.concat([['line', line()], ['col', column()]]);
+          },
+        peg$c8 = "/",
+        peg$c9 = { type: "literal", value: "/", description: "\"/\"" },
+        peg$c10 = function(t) {
+            t.push(["bodies"]);
+            return t.concat([['line', line()], ['col', column()]]);
+          },
+        peg$c11 = /^[#?\^<+@%]/,
+        peg$c12 = { type: "class", value: "[#?\\^<+@%]", description: "[#?\\^<+@%]" },
+        peg$c13 = function(t, n, c, p) { return [t, n, c, p] },
+        peg$c14 = { type: "other", description: "end tag" },
+        peg$c15 = function(n) { return n },
+        peg$c16 = ":",
+        peg$c17 = { type: "literal", value: ":", description: "\":\"" },
+        peg$c18 = function(n) {return n},
+        peg$c19 = function(n) { return n ? ["context", n] : ["context"] },
+        peg$c20 = { type: "other", description: "params" },
+        peg$c21 = "=",
+        peg$c22 = { type: "literal", value: "=", description: "\"=\"" },
+        peg$c23 = function(k, v) {return ["param", ["literal", k], v]},
+        peg$c24 = function(p) { return ["params"].concat(p) },
+        peg$c25 = { type: "other", description: "bodies" },
+        peg$c26 = function(p) { return ["bodies"].concat(p) },
+        peg$c27 = { type: "other", description: "reference" },
+        peg$c28 = function(n, f) { return ["reference", n, f].concat([['line', line()], ['col', column()]]) },
+        peg$c29 = { type: "other", description: "partial" },
+        peg$c30 = ">",
+        peg$c31 = { type: "literal", value: ">", description: "\">\"" },
+        peg$c32 = "+",
+        peg$c33 = { type: "literal", value: "+", description: "\"+\"" },
+        peg$c34 = function(k) {return ["literal", k]},
+        peg$c35 = function(s, n, c, p) {
+            var key = (s === ">") ? "partial" : s;
+            return [key, n, c, p].concat([['line', line()], ['col', column()]]);
+          },
+        peg$c36 = { type: "other", description: "filters" },
+        peg$c37 = "|",
+        peg$c38 = { type: "literal", value: "|", description: "\"|\"" },
+        peg$c39 = function(f) { return ["filters"].concat(f) },
+        peg$c40 = { type: "other", description: "special" },
+        peg$c41 = "~",
+        peg$c42 = { type: "literal", value: "~", description: "\"~\"" },
+        peg$c43 = function(k) { return ["special", k].concat([['line', line()], ['col', column()]]) },
+        peg$c44 = { type: "other", description: "identifier" },
+        peg$c45 = function(p) { var arr = ["path"].concat(p); arr.text = p[1].join('.'); return arr; },
+        peg$c46 = function(k) { var arr = ["key", k]; arr.text = k; return arr; },
+        peg$c47 = { type: "other", description: "number" },
+        peg$c48 = function(n) { return ['literal', n]; },
+        peg$c49 = { type: "other", description: "float" },
+        peg$c50 = ".",
+        peg$c51 = { type: "literal", value: ".", description: "\".\"" },
+        peg$c52 = function(l, r) { return parseFloat(l + "." + r.join('')); },
+        peg$c53 = { type: "other", description: "integer" },
+        peg$c54 = /^[0-9]/,
+        peg$c55 = { type: "class", value: "[0-9]", description: "[0-9]" },
+        peg$c56 = function(digits) { return parseInt(digits.join(""), 10); },
+        peg$c57 = { type: "other", description: "path" },
+        peg$c58 = function(k, d) {
+            d = d[0];
+            if (k && d) {
+              d.unshift(k);
+              return [false, d].concat([['line', line()], ['col', column()]]);
+            }
+            return [true, d].concat([['line', line()], ['col', column()]]);
+          },
+        peg$c59 = function(d) {
+            if (d.length > 0) {
+              return [true, d[0]].concat([['line', line()], ['col', column()]]);
+            }
+            return [true, []].concat([['line', line()], ['col', column()]]);
+          },
+        peg$c60 = { type: "other", description: "key" },
+        peg$c61 = /^[a-zA-Z_$]/,
+        peg$c62 = { type: "class", value: "[a-zA-Z_$]", description: "[a-zA-Z_$]" },
+        peg$c63 = /^[0-9a-zA-Z_$\-]/,
+        peg$c64 = { type: "class", value: "[0-9a-zA-Z_$\\-]", description: "[0-9a-zA-Z_$\\-]" },
+        peg$c65 = function(h, t) { return h + t.join('') },
+        peg$c66 = { type: "other", description: "array" },
+        peg$c67 = function(n) {return n.join('')},
+        peg$c68 = function(a) {return a; },
+        peg$c69 = function(i, nk) { if(nk) { nk.unshift(i); } else {nk = [i] } return nk; },
+        peg$c70 = { type: "other", description: "array_part" },
+        peg$c71 = function(k) {return k},
+        peg$c72 = function(d, a) { if (a) { return d.concat(a); } else { return d; } },
+        peg$c73 = { type: "other", description: "inline" },
+        peg$c74 = "\"",
+        peg$c75 = { type: "literal", value: "\"", description: "\"\\\"\"" },
+        peg$c76 = function() { return ["literal", ""].concat([['line', line()], ['col', column()]]) },
+        peg$c77 = function(l) { return ["literal", l].concat([['line', line()], ['col', column()]]) },
+        peg$c78 = function(p) { return ["body"].concat(p).concat([['line', line()], ['col', column()]]) },
+        peg$c79 = function(l) { return ["buffer", l] },
+        peg$c80 = { type: "other", description: "buffer" },
+        peg$c81 = function(e, w) { return ["format", e, w.join('')].concat([['line', line()], ['col', column()]]) },
+        peg$c82 = { type: "any", description: "any character" },
+        peg$c83 = function(c) {return c},
+        peg$c84 = function(b) { return ["buffer", b.join('')].concat([['line', line()], ['col', column()]]) },
+        peg$c85 = { type: "other", description: "literal" },
+        peg$c86 = /^[^"]/,
+        peg$c87 = { type: "class", value: "[^\"]", description: "[^\"]" },
+        peg$c88 = function(b) { return b.join('') },
+        peg$c89 = "\\\"",
+        peg$c90 = { type: "literal", value: "\\\"", description: "\"\\\\\\\"\"" },
+        peg$c91 = function() { return '"' },
+        peg$c92 = { type: "other", description: "raw" },
+        peg$c93 = "{`",
+        peg$c94 = { type: "literal", value: "{`", description: "\"{`\"" },
+        peg$c95 = "`}",
+        peg$c96 = { type: "literal", value: "`}", description: "\"`}\"" },
+        peg$c97 = function(char) {return char},
+        peg$c98 = function(rawText) { return ["raw", rawText.join('')].concat([['line', line()], ['col', column()]]) },
+        peg$c99 = { type: "other", description: "comment" },
+        peg$c100 = "{!",
+        peg$c101 = { type: "literal", value: "{!", description: "\"{!\"" },
+        peg$c102 = "!}",
+        peg$c103 = { type: "literal", value: "!}", description: "\"!}\"" },
+        peg$c104 = function(c) { return ["comment", c.join('')].concat([['line', line()], ['col', column()]]) },
+        peg$c105 = /^[#?\^><+%:@\/~%]/,
+        peg$c106 = { type: "class", value: "[#?\\^><+%:@\\/~%]", description: "[#?\\^><+%:@\\/~%]" },
+        peg$c107 = "{",
+        peg$c108 = { type: "literal", value: "{", description: "\"{\"" },
+        peg$c109 = "}",
+        peg$c110 = { type: "literal", value: "}", description: "\"}\"" },
+        peg$c111 = "[",
+        peg$c112 = { type: "literal", value: "[", description: "\"[\"" },
+        peg$c113 = "]",
+        peg$c114 = { type: "literal", value: "]", description: "\"]\"" },
+        peg$c115 = "\n",
+        peg$c116 = { type: "literal", value: "\n", description: "\"\\n\"" },
+        peg$c117 = "\r\n",
+        peg$c118 = { type: "literal", value: "\r\n", description: "\"\\r\\n\"" },
+        peg$c119 = "\r",
+        peg$c120 = { type: "literal", value: "\r", description: "\"\\r\"" },
+        peg$c121 = "\u2028",
+        peg$c122 = { type: "literal", value: "\u2028", description: "\"\\u2028\"" },
+        peg$c123 = "\u2029",
+        peg$c124 = { type: "literal", value: "\u2029", description: "\"\\u2029\"" },
+        peg$c125 = /^[\t\x0B\f \xA0\uFEFF]/,
+        peg$c126 = { type: "class", value: "[\\t\\x0B\\f \\xA0\\uFEFF]", description: "[\\t\\x0B\\f \\xA0\\uFEFF]" },
+
+        peg$currPos          = 0,
+        peg$reportedPos      = 0,
+        peg$cachedPos        = 0,
+        peg$cachedPosDetails = { line: 1, column: 1, seenCR: false },
+        peg$maxFailPos       = 0,
+        peg$maxFailExpected  = [],
+        peg$silentFails      = 0,
+
+        peg$result;
+
+    if ("startRule" in options) {
+      if (!(options.startRule in peg$startRuleFunctions)) {
+        throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
+      }
+
+      peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
+    }
+
+    function text() {
+      return input.substring(peg$reportedPos, peg$currPos);
+    }
+
+    function offset() {
+      return peg$reportedPos;
+    }
+
+    function line() {
+      return peg$computePosDetails(peg$reportedPos).line;
+    }
+
+    function column() {
+      return peg$computePosDetails(peg$reportedPos).column;
+    }
+
+    function expected(description) {
+      throw peg$buildException(
+        null,
+        [{ type: "other", description: description }],
+        peg$reportedPos
+      );
+    }
+
+    function error(message) {
+      throw peg$buildException(message, null, peg$reportedPos);
+    }
+
+    function peg$computePosDetails(pos) {
+      function advance(details, startPos, endPos) {
+        var p, ch;
+
+        for (p = startPos; p < endPos; p++) {
+          ch = input.charAt(p);
           if (ch === "\n") {
-            if (!pos.seenCR) { pos.line++; }
-            pos.column = 1;
-            pos.seenCR = false;
+            if (!details.seenCR) { details.line++; }
+            details.column = 1;
+            details.seenCR = false;
           } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
-            pos.line++;
-            pos.column = 1;
-            pos.seenCR = true;
+            details.line++;
+            details.column = 1;
+            details.seenCR = true;
           } else {
-            pos.column++;
-            pos.seenCR = false;
-          }
-        }
-        
-        pos.offset += n;
-      }
-      
-      function matchFailed(failure) {
-        if (pos.offset < rightmostFailuresPos.offset) {
-          return;
-        }
-        
-        if (pos.offset > rightmostFailuresPos.offset) {
-          rightmostFailuresPos = clone(pos);
-          rightmostFailuresExpected = [];
-        }
-        
-        rightmostFailuresExpected.push(failure);
-      }
-      
-      function parse_body() {
-        var result0, result1;
-        var pos0;
-        
-        pos0 = clone(pos);
-        result0 = [];
-        result1 = parse_part();
-        while (result1 !== null) {
-          result0.push(result1);
-          result1 = parse_part();
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, p) { return ["body"].concat(p).concat([['line', line], ['col', column]]) })(pos0.offset, pos0.line, pos0.column, result0);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        return result0;
-      }
-      
-      function parse_part() {
-        var result0;
-        
-        result0 = parse_raw();
-        if (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();
-                  }
+            details.column++;
+            details.seenCR = false;
+          }
+        }
+      }
+
+      if (peg$cachedPos !== pos) {
+        if (peg$cachedPos > pos) {
+          peg$cachedPos = 0;
+          peg$cachedPosDetails = { line: 1, column: 1, seenCR: false };
+        }
+        advance(peg$cachedPosDetails, peg$cachedPos, pos);
+        peg$cachedPos = pos;
+      }
+
+      return peg$cachedPosDetails;
+    }
+
+    function peg$fail(expected) {
+      if (peg$currPos < peg$maxFailPos) { return; }
+
+      if (peg$currPos > peg$maxFailPos) {
+        peg$maxFailPos = peg$currPos;
+        peg$maxFailExpected = [];
+      }
+
+      peg$maxFailExpected.push(expected);
+    }
+
+    function peg$buildException(message, expected, pos) {
+      function cleanupExpected(expected) {
+        var i = 1;
+
+        expected.sort(function(a, b) {
+          if (a.description < b.description) {
+            return -1;
+          } else if (a.description > b.description) {
+            return 1;
+          } else {
+            return 0;
+          }
+        });
+
+        while (i < expected.length) {
+          if (expected[i - 1] === expected[i]) {
+            expected.splice(i, 1);
+          } else {
+            i++;
+          }
+        }
+      }
+
+      function buildMessage(expected, found) {
+        function stringEscape(s) {
+          function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); }
+
+          return s
+            .replace(/\\/g,   '\\\\')
+            .replace(/"/g,    '\\"')
+            .replace(/\x08/g, '\\b')
+            .replace(/\t/g,   '\\t')
+            .replace(/\n/g,   '\\n')
+            .replace(/\f/g,   '\\f')
+            .replace(/\r/g,   '\\r')
+            .replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
+            .replace(/[\x10-\x1F\x80-\xFF]/g,    function(ch) { return '\\x'  + hex(ch); })
+            .replace(/[\u0180-\u0FFF]/g,         function(ch) { return '\\u0' + hex(ch); })
+            .replace(/[\u1080-\uFFFF]/g,         function(ch) { return '\\u'  + hex(ch); });
+        }
+
+        var expectedDescs = new Array(expected.length),
+            expectedDesc, foundDesc, i;
+
+        for (i = 0; i < expected.length; i++) {
+          expectedDescs[i] = expected[i].description;
+        }
+
+        expectedDesc = expected.length > 1
+          ? expectedDescs.slice(0, -1).join(", ")
+              + " or "
+              + expectedDescs[expected.length - 1]
+          : expectedDescs[0];
+
+        foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input";
+
+        return "Expected " + expectedDesc + " but " + foundDesc + " found.";
+      }
+
+      var posDetails = peg$computePosDetails(pos),
+          found      = pos < input.length ? input.charAt(pos) : null;
+
+      if (expected !== null) {
+        cleanupExpected(expected);
+      }
+
+      return new SyntaxError(
+        message !== null ? message : buildMessage(expected, found),
+        expected,
+        found,
+        pos,
+        posDetails.line,
+        posDetails.column
+      );
+    }
+
+    function peg$parsestart() {
+      var s0;
+
+      s0 = peg$parsebody();
+
+      return s0;
+    }
+
+    function peg$parsebody() {
+      var s0, s1, s2;
+
+      s0 = peg$currPos;
+      s1 = [];
+      s2 = peg$parsepart();
+      while (s2 !== peg$FAILED) {
+        s1.push(s2);
+        s2 = peg$parsepart();
+      }
+      if (s1 !== peg$FAILED) {
+        peg$reportedPos = s0;
+        s1 = peg$c1(s1);
+      }
+      s0 = s1;
+
+      return s0;
+    }
+
+    function peg$parsepart() {
+      var s0;
+
+      s0 = peg$parseraw();
+      if (s0 === peg$FAILED) {
+        s0 = peg$parsecomment();
+        if (s0 === peg$FAILED) {
+          s0 = peg$parsesection();
+          if (s0 === peg$FAILED) {
+            s0 = peg$parsepartial();
+            if (s0 === peg$FAILED) {
+              s0 = peg$parsespecial();
+              if (s0 === peg$FAILED) {
+                s0 = peg$parsereference();
+                if (s0 === peg$FAILED) {
+                  s0 = peg$parsebuffer();
                 }
               }
             }
           }
         }
-        return result0;
-      }
-      
-      function parse_section() {
-        var result0, result1, result2, result3, result4, result5, result6;
-        var pos0, pos1;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        pos1 = clone(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();
-                  result5 = result5 !== null ? result5 : "";
-                  if (result5 !== null) {
-                    result6 = (function(offset, line, column, t, b, e, n) {if( (!n) || (t[1].text !== n.text) ) { throw new Error("Expected end tag for "+t[1].text+" but it was not found. At line : "+line+", column : " + column)} return true;})(pos.offset, pos.line, pos.column, result0, result3, result4, result5) ? "" : null;
-                    if (result6 !== null) {
-                      result0 = [result0, result1, result2, result3, result4, result5, result6];
-                    } else {
-                      result0 = null;
-                      pos = clone(pos1);
-                    }
+      }
+
+      return s0;
+    }
+
+    function peg$parsesection() {
+      var s0, s1, s2, s3, s4, s5, s6, s7;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      s1 = peg$parsesec_tag_start();
+      if (s1 !== peg$FAILED) {
+        s2 = [];
+        s3 = peg$parsews();
+        while (s3 !== peg$FAILED) {
+          s2.push(s3);
+          s3 = peg$parsews();
+        }
+        if (s2 !== peg$FAILED) {
+          s3 = peg$parserd();
+          if (s3 !== peg$FAILED) {
+            s4 = peg$parsebody();
+            if (s4 !== peg$FAILED) {
+              s5 = peg$parsebodies();
+              if (s5 !== peg$FAILED) {
+                s6 = peg$parseend_tag();
+                if (s6 === peg$FAILED) {
+                  s6 = peg$c4;
+                }
+                if (s6 !== peg$FAILED) {
+                  peg$reportedPos = peg$currPos;
+                  s7 = peg$c5(s1, s4, s5, s6);
+                  if (s7) {
+                    s7 = peg$c6;
                   } else {
-                    result0 = null;
-                    pos = clone(pos1);
+                    s7 = peg$c3;
+                  }
+                  if (s7 !== peg$FAILED) {
+                    peg$reportedPos = s0;
+                    s1 = peg$c7(s1, s4, s5, s6);
+                    s0 = s1;
+                  } else {
+                    peg$currPos = s0;
+                    s0 = peg$c3;
                   }
                 } else {
-                  result0 = null;
-                  pos = clone(pos1);
+                  peg$currPos = s0;
+                  s0 = peg$c3;
                 }
               } else {
-                result0 = null;
-                pos = clone(pos1);
+                peg$currPos = s0;
+                s0 = peg$c3;
               }
             } else {
-              result0 = null;
-              pos = clone(pos1);
+              peg$currPos = s0;
+              s0 = peg$c3;
             }
           } else {
-            result0 = null;
-            pos = clone(pos1);
+            peg$currPos = s0;
+            s0 = peg$c3;
           }
         } else {
-          result0 = null;
-          pos = clone(pos1);
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, t, b, e, n) { e.push(["param", ["literal", "block"], b]); t.push(e); return t.concat([['line', line], ['col', column]]) })(pos0.offset, pos0.line, pos0.column, result0[0], result0[3], result0[4], result0[5]);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        if (result0 === null) {
-          pos0 = clone(pos);
-          pos1 = clone(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) {
-              if (input.charCodeAt(pos.offset) === 47) {
-                result2 = "/";
-                advance(pos, 1);
-              } else {
-                result2 = null;
-                if (reportFailures === 0) {
-                  matchFailed("\"/\"");
-                }
-              }
-              if (result2 !== null) {
-                result3 = parse_rd();
-                if (result3 !== null) {
-                  result0 = [result0, result1, result2, result3];
-                } else {
-                  result0 = null;
-                  pos = clone(pos1);
-                }
+          peg$currPos = s0;
+          s0 = peg$c3;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c3;
+      }
+      if (s0 === peg$FAILED) {
+        s0 = peg$currPos;
+        s1 = peg$parsesec_tag_start();
+        if (s1 !== peg$FAILED) {
+          s2 = [];
+          s3 = peg$parsews();
+          while (s3 !== peg$FAILED) {
+            s2.push(s3);
+            s3 = peg$parsews();
+          }
+          if (s2 !== peg$FAILED) {
+            if (input.charCodeAt(peg$currPos) === 47) {
+              s3 = peg$c8;
+              peg$currPos++;
+            } else {
+              s3 = peg$FAILED;
+              if (peg$silentFails === 0) { peg$fail(peg$c9); }
+            }
+            if (s3 !== peg$FAILED) {
+              s4 = peg$parserd();
+              if (s4 !== peg$FAILED) {
+                peg$reportedPos = s0;
+                s1 = peg$c10(s1);
+                s0 = s1;
               } else {
-                result0 = null;
-                pos = clone(pos1);
+                peg$currPos = s0;
+                s0 = peg$c3;
               }
             } else {
-              result0 = null;
-              pos = clone(pos1);
+              peg$currPos = s0;
+              s0 = peg$c3;
             }
           } else {
-            result0 = null;
-            pos = clone(pos1);
-          }
-          if (result0 !== null) {
-            result0 = (function(offset, line, column, t) { t.push(["bodies"]); return t.concat([['line', line], ['col', column]]) })(pos0.offset, pos0.line, pos0.column, result0[0]);
-          }
-          if (result0 === null) {
-            pos = clone(pos0);
-          }
-        }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("section");
-        }
-        return result0;
-      }
-      
-      function parse_sec_tag_start() {
-        var result0, result1, result2, result3, result4, result5;
-        var pos0, pos1;
-        
-        pos0 = clone(pos);
-        pos1 = clone(pos);
-        result0 = parse_ld();
-        if (result0 !== null) {
-          if (/^[#?^<+@%]/.test(input.charAt(pos.offset))) {
-            result1 = input.charAt(pos.offset);
-            advance(pos, 1);
-          } else {
-            result1 = null;
-            if (reportFailures === 0) {
-              matchFailed("[#?^<+@%]");
-            }
+            peg$currPos = s0;
+            s0 = peg$c3;
           }
-          if (result1 !== null) {
-            result2 = [];
-            result3 = parse_ws();
-            while (result3 !== null) {
-              result2.push(result3);
-              result3 = parse_ws();
-            }
-            if (result2 !== null) {
-              result3 = parse_identifier();
-              if (result3 !== null) {
-                result4 = parse_context();
-                if (result4 !== null) {
-                  result5 = parse_params();
-                  if (result5 !== null) {
-                    result0 = [result0, result1, result2, result3, result4, result5];
-                  } else {
-                    result0 = null;
-                    pos = clone(pos1);
-                  }
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c3;
+        }
+      }
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c2); }
+      }
+
+      return s0;
+    }
+
+    function peg$parsesec_tag_start() {
+      var s0, s1, s2, s3, s4, s5, s6;
+
+      s0 = peg$currPos;
+      s1 = peg$parseld();
+      if (s1 !== peg$FAILED) {
+        if (peg$c11.test(input.charAt(peg$currPos))) {
+          s2 = input.charAt(peg$currPos);
+          peg$currPos++;
+        } else {
+          s2 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c12); }
+        }
+        if (s2 !== peg$FAILED) {
+          s3 = [];
+          s4 = peg$parsews();
+          while (s4 !== peg$FAILED) {
+            s3.push(s4);
+            s4 = peg$parsews();
+          }
+          if (s3 !== peg$FAILED) {
+            s4 = peg$parseidentifier();
+            if (s4 !== peg$FAILED) {
+              s5 = peg$parsecontext();
+              if (s5 !== peg$FAILED) {
+                s6 = peg$parseparams();
+                if (s6 !== peg$FAILED) {
+                  peg$reportedPos = s0;
+                  s1 = peg$c13(s2, s4, s5, s6);
+                  s0 = s1;
                 } else {
-                  result0 = null;
-                  pos = clone(pos1);
+                  peg$currPos = s0;
+                  s0 = peg$c3;
                 }
               } else {
-                result0 = null;
-                pos = clone(pos1);
+                peg$currPos = s0;
+                s0 = peg$c3;
               }
             } else {
-              result0 = null;
-              pos = clone(pos1);
+              peg$currPos = s0;
+              s0 = peg$c3;
             }
           } else {
-            result0 = null;
-            pos = clone(pos1);
+            peg$currPos = s0;
+            s0 = peg$c3;
           }
         } else {
-          result0 = null;
-          pos = clone(pos1);
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, t, n, c, p) { return [t, n, c, p] })(pos0.offset, pos0.line, pos0.column, result0[1], result0[3], result0[4], result0[5]);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        return result0;
-      }
-      
-      function parse_end_tag() {
-        var result0, result1, result2, result3, result4, result5;
-        var pos0, pos1;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        pos1 = clone(pos);
-        result0 = parse_ld();
-        if (result0 !== null) {
-          if (input.charCodeAt(pos.offset) === 47) {
-            result1 = "/";
-            advance(pos, 1);
-          } else {
-            result1 = null;
-            if (reportFailures === 0) {
-              matchFailed("\"/\"");
-            }
-          }
-          if (result1 !== null) {
-            result2 = [];
-            result3 = parse_ws();
-            while (result3 !== null) {
-              result2.push(result3);
-              result3 = parse_ws();
-            }
-            if (result2 !== null) {
-              result3 = parse_identifier();
-              if (result3 !== null) {
-                result4 = [];
-                result5 = parse_ws();
-                while (result5 !== null) {
-                  result4.push(result5);
-                  result5 = parse_ws();
-                }
-                if (result4 !== null) {
-                  result5 = parse_rd();
-                  if (result5 !== null) {
-                    result0 = [result0, result1, result2, result3, result4, result5];
-                  } else {
-                    result0 = null;
-                    pos = clone(pos1);
-                  }
+          peg$currPos = s0;
+          s0 = peg$c3;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c3;
+      }
+
+      return s0;
+    }
+
+    function peg$parseend_tag() {
+      var s0, s1, s2, s3, s4, s5, s6;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      s1 = peg$parseld();
+      if (s1 !== peg$FAILED) {
+        if (input.charCodeAt(peg$currPos) === 47) {
+          s2 = peg$c8;
+          peg$currPos++;
+        } else {
+          s2 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c9); }
+        }
+        if (s2 !== peg$FAILED) {
+          s3 = [];
+          s4 = peg$parsews();
+          while (s4 !== peg$FAILED) {
+            s3.push(s4);
+            s4 = peg$parsews();
+          }
+          if (s3 !== peg$FAILED) {
+            s4 = peg$parseidentifier();
+            if (s4 !== peg$FAILED) {
+              s5 = [];
+              s6 = peg$parsews();
+              while (s6 !== peg$FAILED) {
+                s5.push(s6);
+                s6 = peg$parsews();
+              }
+              if (s5 !== peg$FAILED) {
+                s6 = peg$parserd();
+                if (s6 !== peg$FAILED) {
+                  peg$reportedPos = s0;
+                  s1 = peg$c15(s4);
+                  s0 = s1;
                 } else {
-                  result0 = null;
-                  pos = clone(pos1);
+                  peg$currPos = s0;
+                  s0 = peg$c3;
                 }
               } else {
-                result0 = null;
-                pos = clone(pos1);
+                peg$currPos = s0;
+                s0 = peg$c3;
               }
             } else {
-              result0 = null;
-              pos = clone(pos1);
+              peg$currPos = s0;
+              s0 = peg$c3;
             }
           } else {
-            result0 = null;
-            pos = clone(pos1);
+            peg$currPos = s0;
+            s0 = peg$c3;
           }
         } else {
-          result0 = null;
-          pos = clone(pos1);
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, n) { return n })(pos0.offset, pos0.line, pos0.column, result0[3]);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("end tag");
-        }
-        return result0;
-      }
-      
-      function parse_context() {
-        var result0, result1;
-        var pos0, pos1, pos2;
-        
-        pos0 = clone(pos);
-        pos1 = clone(pos);
-        pos2 = clone(pos);
-        if (input.charCodeAt(pos.offset) === 58) {
-          result0 = ":";
-          advance(pos, 1);
+          peg$currPos = s0;
+          s0 = peg$c3;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c3;
+      }
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c14); }
+      }
+
+      return s0;
+    }
+
+    function peg$parsecontext() {
+      var s0, s1, s2, s3;
+
+      s0 = peg$currPos;
+      s1 = peg$currPos;
+      if (input.charCodeAt(peg$currPos) === 58) {
+        s2 = peg$c16;
+        peg$currPos++;
+      } else {
+        s2 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c17); }
+      }
+      if (s2 !== peg$FAILED) {
+        s3 = peg$parseidentifier();
+        if (s3 !== peg$FAILED) {
+          peg$reportedPos = s1;
+          s2 = peg$c18(s3);
+          s1 = s2;
         } else {
-          result0 = null;
-          if (reportFailures === 0) {
-            matchFailed("\":\"");
-          }
+          peg$currPos = s1;
+          s1 = peg$c3;
         }
-        if (result0 !== null) {
-          result1 = parse_identifier();
-          if (result1 !== null) {
-            result0 = [result0, result1];
+      } else {
+        peg$currPos = s1;
+        s1 = peg$c3;
+      }
+      if (s1 === peg$FAILED) {
+        s1 = peg$c4;
+      }
+      if (s1 !== peg$FAILED) {
+        peg$reportedPos = s0;
+        s1 = peg$c19(s1);
+      }
+      s0 = s1;
+
+      return s0;
+    }
+
+    function peg$parseparams() {
+      var s0, s1, s2, s3, s4, s5, s6;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      s1 = [];
+      s2 = peg$currPos;
+      s3 = [];
+      s4 = peg$parsews();
+      if (s4 !== peg$FAILED) {
+        while (s4 !== peg$FAILED) {
+          s3.push(s4);
+          s4 = peg$parsews();
+        }
+      } else {
+        s3 = peg$c3;
+      }
+      if (s3 !== peg$FAILED) {
+        s4 = peg$parsekey();
+        if (s4 !== peg$FAILED) {
+          if (input.charCodeAt(peg$currPos) === 61) {
+            s5 = peg$c21;
+            peg$currPos++;
           } else {
-            result0 = null;
-            pos = clone(pos2);
-          }
-        } else {
-          result0 = null;
-          pos = clone(pos2);
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, n) {return n})(pos1.offset, pos1.line, pos1.column, result0[1]);
-        }
-        if (result0 === null) {
-          pos = clone(pos1);
-        }
-        result0 = result0 !== null ? result0 : "";
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, n) { return n ? ["context", n] : ["context"] })(pos0.offset, pos0.line, pos0.column, result0);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        return result0;
-      }
-      
-      function parse_params() {
-        var result0, result1, result2, result3, result4;
-        var pos0, pos1, pos2;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        result0 = [];
-        pos1 = clone(pos);
-        pos2 = clone(pos);
-        result2 = parse_ws();
-        if (result2 !== null) {
-          result1 = [];
-          while (result2 !== null) {
-            result1.push(result2);
-            result2 = parse_ws();
-          }
-        } else {
-          result1 = null;
-        }
-        if (result1 !== null) {
-          result2 = parse_key();
-          if (result2 !== null) {
-            if (input.charCodeAt(pos.offset) === 61) {
-              result3 = "=";
-              advance(pos, 1);
-            } else {
-              result3 = null;
-              if (reportFailures === 0) {
-                matchFailed("\"=\"");
+            s5 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c22); }
+          }
+          if (s5 !== peg$FAILED) {
+            s6 = peg$parsenumber();
+            if (s6 === peg$FAILED) {
+              s6 = peg$parseidentifier();
+              if (s6 === peg$FAILED) {
+                s6 = peg$parseinline();
               }
             }
-            if (result3 !== null) {
-              result4 = parse_number();
-              if (result4 === null) {
-                result4 = parse_identifier();
-                if (result4 === null) {
-                  result4 = parse_inline();
-                }
-              }
-              if (result4 !== null) {
-                result1 = [result1, result2, result3, result4];
-              } else {
-                result1 = null;
-                pos = clone(pos2);
-              }
+            if (s6 !== peg$FAILED) {
+              peg$reportedPos = s2;
+              s3 = peg$c23(s4, s6);
+              s2 = s3;
             } else {
-              result1 = null;
-              pos = clone(pos2);
+              peg$currPos = s2;
+              s2 = peg$c3;
             }
           } else {
-            result1 = null;
-            pos = clone(pos2);
+            peg$currPos = s2;
+            s2 = peg$c3;
           }
         } else {
-          result1 = null;
-          pos = clone(pos2);
-        }
-        if (result1 !== null) {
-          result1 = (function(offset, line, column, k, v) {return ["param", ["literal", k], v]})(pos1.offset, pos1.line, pos1.column, result1[1], result1[3]);
-        }
-        if (result1 === null) {
-          pos = clone(pos1);
-        }
-        while (result1 !== null) {
-          result0.push(result1);
-          pos1 = clone(pos);
-          pos2 = clone(pos);
-          result2 = parse_ws();
-          if (result2 !== null) {
-            result1 = [];
-            while (result2 !== null) {
-              result1.push(result2);
-              result2 = parse_ws();
-            }
-          } else {
-            result1 = null;
-          }
-          if (result1 !== null) {
-            result2 = parse_key();
-            if (result2 !== null) {
-              if (input.charCodeAt(pos.offset) === 61) {
-                result3 = "=";
-                advance(pos, 1);
-              } else {
-                result3 = null;
-                if (reportFailures === 0) {
-                  matchFailed("\"=\"");
+          peg$currPos = s2;
+          s2 = peg$c3;
+        }
+      } else {
+        peg$currPos = s2;
+        s2 = peg$c3;
+      }
+      while (s2 !== peg$FAILED) {
+        s1.push(s2);
+        s2 = peg$currPos;
+        s3 = [];
+        s4 = peg$parsews();
+        if (s4 !== peg$FAILED) {
+          while (s4 !== peg$FAILED) {
+            s3.push(s4);
+            s4 = peg$parsews();
+          }
+        } else {
+          s3 = peg$c3;
+        }
+        if (s3 !== peg$FAILED) {
+          s4 = peg$parsekey();
+          if (s4 !== peg$FAILED) {
+            if (input.charCodeAt(peg$currPos) === 61) {
+              s5 = peg$c21;
+              peg$currPos++;
+            } else {
+              s5 = peg$FAILED;
+              if (peg$silentFails === 0) { peg$fail(peg$c22); }
+            }
+            if (s5 !== peg$FAILED) {
+              s6 = peg$parsenumber();
+              if (s6 === peg$FAILED) {
+                s6 = peg$parseidentifier();
+                if (s6 === peg$FAILED) {
+                  s6 = peg$parseinline();
                 }
               }
-              if (result3 !== null) {
-                result4 = parse_number();
-                if (result4 === null) {
-                  result4 = parse_identifier();
-                  if (result4 === null) {
-                    result4 = parse_inline();
-                  }
-                }
-                if (result4 !== null) {
-                  result1 = [result1, result2, result3, result4];
-                } else {
-                  result1 = null;
-                  pos = clone(pos2);
-                }
+              if (s6 !== peg$FAILED) {
+                peg$reportedPos = s2;
+                s3 = peg$c23(s4, s6);
+                s2 = s3;
               } else {
-                result1 = null;
-                pos = clone(pos2);
+                peg$currPos = s2;
+                s2 = peg$c3;
               }
             } else {
-              result1 = null;
-              pos = clone(pos2);
+              peg$currPos = s2;
+              s2 = peg$c3;
             }
           } else {
-            result1 = null;
-            pos = clone(pos2);
-          }
-          if (result1 !== null) {
-            result1 = (function(offset, line, column, k, v) {return ["param", ["literal", k], v]})(pos1.offset, pos1.line, pos1.column, result1[1], result1[3]);
-          }
-          if (result1 === null) {
-            pos = clone(pos1);
-          }
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, p) { return ["params"].concat(p) })(pos0.offset, pos0.line, pos0.column, result0);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("params");
-        }
-        return result0;
-      }
-      
-      function parse_bodies() {
-        var result0, result1, result2, result3, result4, result5;
-        var pos0, pos1, pos2;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        result0 = [];
-        pos1 = clone(pos);
-        pos2 = clone(pos);
-        result1 = parse_ld();
-        if (result1 !== null) {
-          if (input.charCodeAt(pos.offset) === 58) {
-            result2 = ":";
-            advance(pos, 1);
-          } else {
-            result2 = null;
-            if (reportFailures === 0) {
-              matchFailed("\":\"");
-            }
+            peg$currPos = s2;
+            s2 = peg$c3;
           }
-          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 {
-                  result1 = null;
-                  pos = clone(pos2);
-                }
+        } else {
+          peg$currPos = s2;
+          s2 = peg$c3;
+        }
+      }
+      if (s1 !== peg$FAILED) {
+        peg$reportedPos = s0;
+        s1 = peg$c24(s1);
+      }
+      s0 = s1;
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c20); }
+      }
+
+      return s0;
+    }
+
+    function peg$parsebodies() {
+      var s0, s1, s2, s3, s4, s5, s6, s7;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      s1 = [];
+      s2 = peg$currPos;
+      s3 = peg$parseld();
+      if (s3 !== peg$FAILED) {
+        if (input.charCodeAt(peg$currPos) === 58) {
+          s4 = peg$c16;
+          peg$currPos++;
+        } else {
+          s4 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c17); }
+        }
+        if (s4 !== peg$FAILED) {
+          s5 = peg$parsekey();
+          if (s5 !== peg$FAILED) {
+            s6 = peg$parserd();
+            if (s6 !== peg$FAILED) {
+              s7 = peg$parsebody();
+              if (s7 !== peg$FAILED) {
+                peg$reportedPos = s2;
+                s3 = peg$c23(s5, s7);
+                s2 = s3;
               } else {
-                result1 = null;
-                pos = clone(pos2);
+                peg$currPos = s2;
+                s2 = peg$c3;
               }
             } else {
-              result1 = null;
-              pos = clone(pos2);
+              peg$currPos = s2;
+              s2 = peg$c3;
             }
           } else {
-            result1 = null;
-            pos = clone(pos2);
+            peg$currPos = s2;
+            s2 = peg$c3;
           }
         } else {
-          result1 = null;
-          pos = clone(pos2);
-        }
-        if (result1 !== null) {
-          result1 = (function(offset, line, column, k, v) {return ["param", ["literal", k], v]})(pos1.offset, pos1.line, pos1.column, result1[2], result1[4]);
-        }
-        if (result1 === null) {
-          pos = clone(pos1);
-        }
-        while (result1 !== null) {
-          result0.push(result1);
-          pos1 = clone(pos);
-          pos2 = clone(pos);
-          result1 = parse_ld();
-          if (result1 !== null) {
-            if (input.charCodeAt(pos.offset) === 58) {
-              result2 = ":";
-              advance(pos, 1);
-            } else {
-              result2 = null;
-              if (reportFailures === 0) {
-                matchFailed("\":\"");
-              }
-            }
-            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 {
-                    result1 = null;
-                    pos = clone(pos2);
-                  }
+          peg$currPos = s2;
+          s2 = peg$c3;
+        }
+      } else {
+        peg$currPos = s2;
+        s2 = peg$c3;
+      }
+      while (s2 !== peg$FAILED) {
+        s1.push(s2);
+        s2 = peg$currPos;
+        s3 = peg$parseld();
+        if (s3 !== peg$FAILED) {
+          if (input.charCodeAt(peg$currPos) === 58) {
+            s4 = peg$c16;
+            peg$currPos++;
+          } else {
+            s4 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c17); }
+          }
+          if (s4 !== peg$FAILED) {
+            s5 = peg$parsekey();
+            if (s5 !== peg$FAILED) {
+              s6 = peg$parserd();
+              if (s6 !== peg$FAILED) {
+                s7 = peg$parsebody();
+                if (s7 !== peg$FAILED) {
+                  peg$reportedPos = s2;
+                  s3 = peg$c23(s5, s7);
+                  s2 = s3;
                 } else {
-                  result1 = null;
-                  pos = clone(pos2);
+                  peg$currPos = s2;
+                  s2 = peg$c3;
                 }
               } else {
-                result1 = null;
-                pos = clone(pos2);
+                peg$currPos = s2;
+                s2 = peg$c3;
               }
             } else {
-              result1 = null;
-              pos = clone(pos2);
+              peg$currPos = s2;
+              s2 = peg$c3;
             }
           } else {
-            result1 = null;
-            pos = clone(pos2);
-          }
-          if (result1 !== null) {
-            result1 = (function(offset, line, column, k, v) {return ["param", ["literal", k], v]})(pos1.offset, pos1.line, pos1.column, result1[2], result1[4]);
-          }
-          if (result1 === null) {
-            pos = clone(pos1);
-          }
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, p) { return ["bodies"].concat(p) })(pos0.offset, pos0.line, pos0.column, result0);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("bodies");
-        }
-        return result0;
-      }
-      
-      function parse_reference() {
-        var result0, result1, result2, result3;
-        var pos0, pos1;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        pos1 = clone(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 {
-                result0 = null;
-                pos = clone(pos1);
-              }
+            peg$currPos = s2;
+            s2 = peg$c3;
+          }
+        } else {
+          peg$currPos = s2;
+          s2 = peg$c3;
+        }
+      }
+      if (s1 !== peg$FAILED) {
+        peg$reportedPos = s0;
+        s1 = peg$c26(s1);
+      }
+      s0 = s1;
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c25); }
+      }
+
+      return s0;
+    }
+
+    function peg$parsereference() {
+      var s0, s1, s2, s3, s4;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      s1 = peg$parseld();
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parseidentifier();
+        if (s2 !== peg$FAILED) {
+          s3 = peg$parsefilters();
+          if (s3 !== peg$FAILED) {
+            s4 = peg$parserd();
+            if (s4 !== peg$FAILED) {
+              peg$reportedPos = s0;
+              s1 = peg$c28(s2, s3);
+              s0 = s1;
             } else {
-              result0 = null;
-              pos = clone(pos1);
+              peg$currPos = s0;
+              s0 = peg$c3;
             }
           } else {
-            result0 = null;
-            pos = clone(pos1);
+            peg$currPos = s0;
+            s0 = peg$c3;
           }
         } else {
-          result0 = null;
-          pos = clone(pos1);
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, n, f) { return ["reference", n, f].concat([['line', line], ['col', column]]) })(pos0.offset, pos0.line, pos0.column, result0[1], result0[2]);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("reference");
-        }
-        return result0;
-      }
-      
-      function parse_partial() {
-        var result0, result1, result2, result3, result4, result5, result6, result7, result8;
-        var pos0, pos1, pos2;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        pos1 = clone(pos);
-        result0 = parse_ld();
-        if (result0 !== null) {
-          if (input.charCodeAt(pos.offset) === 62) {
-            result1 = ">";
-            advance(pos, 1);
+          peg$currPos = s0;
+          s0 = peg$c3;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c3;
+      }
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c27); }
+      }
+
+      return s0;
+    }
+
+    function peg$parsepartial() {
+      var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      s1 = peg$parseld();
+      if (s1 !== peg$FAILED) {
+        if (input.charCodeAt(peg$currPos) === 62) {
+          s2 = peg$c30;
+          peg$currPos++;
+        } else {
+          s2 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c31); }
+        }
+        if (s2 === peg$FAILED) {
+          if (input.charCodeAt(peg$currPos) === 43) {
+            s2 = peg$c32;
+            peg$currPos++;
           } else {
-            result1 = null;
-            if (reportFailures === 0) {
-              matchFailed("\">\"");
-            }
-          }
-          if (result1 === null) {
-            if (input.charCodeAt(pos.offset) === 43) {
-              result1 = "+";
-              advance(pos, 1);
-            } else {
-              result1 = null;
-              if (reportFailures === 0) {
-                matchFailed("\"+\"");
-              }
-            }
-          }
-          if (result1 !== null) {
-            result2 = [];
-            result3 = parse_ws();
-            while (result3 !== null) {
-              result2.push(result3);
-              result3 = parse_ws();
-            }
-            if (result2 !== null) {
-              pos2 = clone(pos);
-              result3 = parse_key();
-              if (result3 !== null) {
-                result3 = (function(offset, line, column, k) {return ["literal", k]})(pos2.offset, pos2.line, pos2.column, result3);
-              }
-              if (result3 === null) {
-                pos = clone(pos2);
-              }
-              if (result3 === null) {
-                result3 = parse_inline();
-              }
-              if (result3 !== null) {
-                result4 = parse_context();
-                if (result4 !== null) {
-                  result5 = parse_params();
-                  if (result5 !== null) {
-                    result6 = [];
-                    result7 = parse_ws();
-                    while (result7 !== null) {
-                      result6.push(result7);
-                      result7 = parse_ws();
+            s2 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c33); }
+          }
+        }
+        if (s2 !== peg$FAILED) {
+          s3 = [];
+          s4 = peg$parsews();
+          while (s4 !== peg$FAILED) {
+            s3.push(s4);
+            s4 = peg$parsews();
+          }
+          if (s3 !== peg$FAILED) {
+            s4 = peg$currPos;
+            s5 = peg$parsekey();
+            if (s5 !== peg$FAILED) {
+              peg$reportedPos = s4;
+              s5 = peg$c34(s5);
+            }
+            s4 = s5;
+            if (s4 === peg$FAILED) {
+              s4 = peg$parseinline();
+            }
+            if (s4 !== peg$FAILED) {
+              s5 = peg$parsecontext();
+              if (s5 !== peg$FAILED) {
+                s6 = peg$parseparams();
+                if (s6 !== peg$FAILED) {
+                  s7 = [];
+                  s8 = peg$parsews();
+                  while (s8 !== peg$FAILED) {
+                    s7.push(s8);
+                    s8 = peg$parsews();
+                  }
+                  if (s7 !== peg$FAILED) {
+                    if (input.charCodeAt(peg$currPos) === 47) {
+                      s8 = peg$c8;
+                      peg$currPos++;
+                    } else {
+                      s8 = peg$FAILED;
+                      if (peg$silentFails === 0) { peg$fail(peg$c9); }
                     }
-                    if (result6 !== null) {
-                      if (input.charCodeAt(pos.offset) === 47) {
-                        result7 = "/";
-                        advance(pos, 1);
-                      } else {
-                        result7 = null;
-                        if (reportFailures === 0) {
-                          matchFailed("\"/\"");
-                        }
-                      }
-                      if (result7 !== null) {
-                        result8 = parse_rd();
-                        if (result8 !== null) {
-                          result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8];
-                        } else {
-                          result0 = null;
-                          pos = clone(pos1);
-                        }
+                    if (s8 !== peg$FAILED) {
+                      s9 = peg$parserd();
+                      if (s9 !== peg$FAILED) {
+                        peg$reportedPos = s0;
+                        s1 = peg$c35(s2, s4, s5, s6);
+                        s0 = s1;
                       } else {
-                        result0 = null;
-                        pos = clone(pos1);
+                        peg$currPos = s0;
+                        s0 = peg$c3;
                       }
                     } else {
-                      result0 = null;
-                      pos = clone(pos1);
+                      peg$currPos = s0;
+                      s0 = peg$c3;
                     }
                   } else {
-                    result0 = null;
-                    pos = clone(pos1);
+                    peg$currPos = s0;
+                    s0 = peg$c3;
                   }
                 } else {
-                  result0 = null;
-                  pos = clone(pos1);
+                  peg$currPos = s0;
+                  s0 = peg$c3;
                 }
               } else {
-                result0 = null;
-                pos = clone(pos1);
+                peg$currPos = s0;
+                s0 = peg$c3;
               }
             } else {
-              result0 = null;
-              pos = clone(pos1);
+              peg$currPos = s0;
+              s0 = peg$c3;
             }
           } else {
-            result0 = null;
-            pos = clone(pos1);
+            peg$currPos = s0;
+            s0 = peg$c3;
           }
         } else {
-          result0 = null;
-          pos = clone(pos1);
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, s, n, c, p) { var key = (s ===">")? "partial" : s; return [key, n, c, p].concat([['line', line], ['col', column]]) })(pos0.offset, pos0.line, pos0.column, result0[1], result0[3], result0[4], result0[5]);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("partial");
-        }
-        return result0;
-      }
-      
-      function parse_filters() {
-        var result0, result1, result2;
-        var pos0, pos1, pos2;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        result0 = [];
-        pos1 = clone(pos);
-        pos2 = clone(pos);
-        if (input.charCodeAt(pos.offset) === 124) {
-          result1 = "|";
-          advance(pos, 1);
+          peg$currPos = s0;
+          s0 = peg$c3;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c3;
+      }
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c29); }
+      }
+
+      return s0;
+    }
+
+    function peg$parsefilters() {
+      var s0, s1, s2, s3, s4;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      s1 = [];
+      s2 = peg$currPos;
+      if (input.charCodeAt(peg$currPos) === 124) {
+        s3 = peg$c37;
+        peg$currPos++;
+      } else {
+        s3 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c38); }
+      }
+      if (s3 !== peg$FAILED) {
+        s4 = peg$parsekey();
+        if (s4 !== peg$FAILED) {
+          peg$reportedPos = s2;
+          s3 = peg$c18(s4);
+          s2 = s3;
         } else {
-          result1 = null;
-          if (reportFailures === 0) {
-            matchFailed("\"|\"");
-          }
+          peg$currPos = s2;
+          s2 = peg$c3;
         }
-        if (result1 !== null) {
-          result2 = parse_key();
-          if (result2 !== null) {
-            result1 = [result1, result2];
-          } else {
-            result1 = null;
-            pos = clone(pos2);
-          }
+      } else {
+        peg$currPos = s2;
+        s2 = peg$c3;
+      }
+      while (s2 !== peg$FAILED) {
+        s1.push(s2);
+        s2 = peg$currPos;
+        if (input.charCodeAt(peg$currPos) === 124) {
+          s3 = peg$c37;
+          peg$currPos++;
         } else {
-          result1 = null;
-          pos = clone(pos2);
-        }
-        if (result1 !== null) {
-          result1 = (function(offset, line, column, n) {return n})(pos1.offset, pos1.line, pos1.column, result1[1]);
-        }
-        if (result1 === null) {
-          pos = clone(pos1);
-        }
-        while (result1 !== null) {
-          result0.push(result1);
-          pos1 = clone(pos);
-          pos2 = clone(pos);
-          if (input.charCodeAt(pos.offset) === 124) {
-            result1 = "|";
-            advance(pos, 1);
+          s3 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c38); }
+        }
+        if (s3 !== peg$FAILED) {
+          s4 = peg$parsekey();
+          if (s4 !== peg$FAILED) {
+            peg$reportedPos = s2;
+            s3 = peg$c18(s4);
+            s2 = s3;
           } else {
-            result1 = null;
-            if (reportFailures === 0) {
-              matchFailed("\"|\"");
-            }
+            peg$currPos = s2;
+            s2 = peg$c3;
           }
-          if (result1 !== null) {
-            result2 = parse_key();
-            if (result2 !== null) {
-              result1 = [result1, result2];
-            } else {
-              result1 = null;
-              pos = clone(pos2);
-            }
-          } else {
-            result1 = null;
-            pos = clone(pos2);
-          }
-          if (result1 !== null) {
-            result1 = (function(offset, line, column, n) {return n})(pos1.offset, pos1.line, pos1.column, result1[1]);
-          }
-          if (result1 === null) {
-            pos = clone(pos1);
-          }
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, f) { return ["filters"].concat(f) })(pos0.offset, pos0.line, pos0.column, result0);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("filters");
+        } else {
+          peg$currPos = s2;
+          s2 = peg$c3;
         }
-        return result0;
       }
-      
-      function parse_special() {
-        var result0, result1, result2, result3;
-        var pos0, pos1;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        pos1 = clone(pos);
-        result0 = parse_ld();
-        if (result0 !== null) {
-          if (input.charCodeAt(pos.offset) === 126) {
-            result1 = "~";
-            advance(pos, 1);
-          } else {
-            result1 = null;
-            if (reportFailures === 0) {
-              matchFailed("\"~\"");
-            }
-          }
-          if (result1 !== null) {
-            result2 = parse_key();
-            if (result2 !== null) {
-              result3 = parse_rd();
-              if (result3 !== null) {
-                result0 = [result0, result1, result2, result3];
-              } else {
-                result0 = null;
-                pos = clone(pos1);
-              }
-            } else {
-              result0 = null;
-              pos = clone(pos1);
-            }
-          } else {
-            result0 = null;
-            pos = clone(pos1);
-          }
+      if (s1 !== peg$FAILED) {
+        peg$reportedPos = s0;
+        s1 = peg$c39(s1);
+      }
+      s0 = s1;
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c36); }
+      }
+
+      return s0;
+    }
+
+    function peg$parsespecial() {
+      var s0, s1, s2, s3, s4;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      s1 = peg$parseld();
+      if (s1 !== peg$FAILED) {
+        if (input.charCodeAt(peg$currPos) === 126) {
+          s2 = peg$c41;
+          peg$currPos++;
         } else {
-          result0 = null;
-          pos = clone(pos1);
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, k) { return ["special", k].concat([['line', line], ['col', column]]) })(pos0.offset, pos0.line, pos0.column, result0[2]);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("special");
-        }
-        return result0;
-      }
-      
-      function parse_identifier() {
-        var result0;
-        var pos0;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        result0 = parse_path();
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, p) { var arr = ["path"].concat(p); arr.text = p[1].join('.'); return arr; })(pos0.offset, pos0.line, pos0.column, result0);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        if (result0 === null) {
-          pos0 = clone(pos);
-          result0 = parse_key();
-          if (result0 !== null) {
-            result0 = (function(offset, line, column, k) { var arr = ["key", k]; arr.text = k; return arr; })(pos0.offset, pos0.line, pos0.column, result0);
-          }
-          if (result0 === null) {
-            pos = clone(pos0);
-          }
-        }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("identifier");
-        }
-        return result0;
-      }
-      
-      function parse_number() {
-        var result0;
-        var pos0;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        result0 = parse_float();
-        if (result0 === null) {
-          result0 = parse_integer();
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, n) { return ['literal', n]; })(pos0.offset, pos0.line, pos0.column, result0);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("number");
-        }
-        return result0;
-      }
-      
-      function parse_float() {
-        var result0, result1, result2, result3;
-        var pos0, pos1;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        pos1 = clone(pos);
-        result0 = parse_integer();
-        if (result0 !== null) {
-          if (input.charCodeAt(pos.offset) === 46) {
-            result1 = ".";
-            advance(pos, 1);
-          } else {
-            result1 = null;
-            if (reportFailures === 0) {
-              matchFailed("\".\"");
-            }
-          }
-          if (result1 !== null) {
-            result3 = parse_integer();
-            if (result3 !== null) {
-              result2 = [];
-              while (result3 !== null) {
-                result2.push(result3);
-                result3 = parse_integer();
-              }
-            } else {
-              result2 = null;
-            }
-            if (result2 !== null) {
-              result0 = [result0, result1, result2];
+          s2 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c42); }
+        }
+        if (s2 !== peg$FAILED) {
+          s3 = peg$parsekey();
+          if (s3 !== peg$FAILED) {
+            s4 = peg$parserd();
+            if (s4 !== peg$FAILED) {
+              peg$reportedPos = s0;
+              s1 = peg$c43(s3);
+              s0 = s1;
             } else {
-              result0 = null;
-              pos = clone(pos1);
+              peg$currPos = s0;
+              s0 = peg$c3;
             }
           } else {
-            result0 = null;
-            pos = clone(pos1);
+            peg$currPos = s0;
+            s0 = peg$c3;
           }
         } else {
-          result0 = null;
-          pos = clone(pos1);
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, l, r) { return parseFloat(l + "." + r.join('')); })(pos0.offset, pos0.line, pos0.column, result0[0], result0[2]);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("float");
-        }
-        return result0;
-      }
-      
-      function parse_integer() {
-        var result0, result1;
-        var pos0;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        if (/^[0-9]/.test(input.charAt(pos.offset))) {
-          result1 = input.charAt(pos.offset);
-          advance(pos, 1);
-        } else {
-          result1 = null;
-          if (reportFailures === 0) {
-            matchFailed("[0-9]");
-          }
-        }
-        if (result1 !== null) {
-          result0 = [];
-          while (result1 !== null) {
-            result0.push(result1);
-            if (/^[0-9]/.test(input.charAt(pos.offset))) {
-              result1 = input.charAt(pos.offset);
-              advance(pos, 1);
-            } else {
-              result1 = null;
-              if (reportFailures === 0) {
-                matchFailed("[0-9]");
-              }
-            }
-          }
+          peg$currPos = s0;
+          s0 = peg$c3;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c3;
+      }
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c40); }
+      }
+
+      return s0;
+    }
+
+    function peg$parseidentifier() {
+      var s0, s1;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      s1 = peg$parsepath();
+      if (s1 !== peg$FAILED) {
+        peg$reportedPos = s0;
+        s1 = peg$c45(s1);
+      }
+      s0 = s1;
+      if (s0 === peg$FAILED) {
+        s0 = peg$currPos;
+        s1 = peg$parsekey();
+        if (s1 !== peg$FAILED) {
+          peg$reportedPos = s0;
+          s1 = peg$c46(s1);
+        }
+        s0 = s1;
+      }
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c44); }
+      }
+
+      return s0;
+    }
+
+    function peg$parsenumber() {
+      var s0, s1;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      s1 = peg$parsefloat();
+      if (s1 === peg$FAILED) {
+        s1 = peg$parseinteger();
+      }
+      if (s1 !== peg$FAILED) {
+        peg$reportedPos = s0;
+        s1 = peg$c48(s1);
+      }
+      s0 = s1;
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c47); }
+      }
+
+      return s0;
+    }
+
+    function peg$parsefloat() {
+      var s0, s1, s2, s3, s4;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      s1 = peg$parseinteger();
+      if (s1 !== peg$FAILED) {
+        if (input.charCodeAt(peg$currPos) === 46) {
+          s2 = peg$c50;
+          peg$currPos++;
         } else {
-          result0 = null;
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, digits) { return parseInt(digits.join(""), 10); })(pos0.offset, pos0.line, pos0.column, result0);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("integer");
-        }
-        return result0;
-      }
-      
-      function parse_path() {
-        var result0, result1, result2;
-        var pos0, pos1;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        pos1 = clone(pos);
-        result0 = parse_key();
-        result0 = result0 !== null ? result0 : "";
-        if (result0 !== null) {
-          result2 = parse_array_part();
-          if (result2 === null) {
-            result2 = parse_array();
-          }
-          if (result2 !== null) {
-            result1 = [];
-            while (result2 !== null) {
-              result1.push(result2);
-              result2 = parse_array_part();
-              if (result2 === null) {
-                result2 = parse_array();
-              }
+          s2 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c51); }
+        }
+        if (s2 !== peg$FAILED) {
+          s3 = [];
+          s4 = peg$parseinteger();
+          if (s4 !== peg$FAILED) {
+            while (s4 !== peg$FAILED) {
+              s3.push(s4);
+              s4 = peg$parseinteger();
             }
           } else {
-            result1 = null;
+            s3 = peg$c3;
           }
-          if (result1 !== null) {
-            result0 = [result0, result1];
+          if (s3 !== peg$FAILED) {
+            peg$reportedPos = s0;
+            s1 = peg$c52(s1, s3);
+            s0 = s1;
           } else {
-            result0 = null;
-            pos = clone(pos1);
+            peg$currPos = s0;
+            s0 = peg$c3;
           }
         } else {
-          result0 = null;
-          pos = clone(pos1);
+          peg$currPos = s0;
+          s0 = peg$c3;
         }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, k, d) {
-            d = d[0];
-            if (k && d) {
-              d.unshift(k);
-              return [false, d].concat([['line', line], ['col', column]]);
-            }
-            return [true, d].concat([['line', line], ['col', column]]);
-          })(pos0.offset, pos0.line, pos0.column, result0[0], result0[1]);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        if (result0 === null) {
-          pos0 = clone(pos);
-          pos1 = clone(pos);
-          if (input.charCodeAt(pos.offset) === 46) {
-            result0 = ".";
-            advance(pos, 1);
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c3;
+      }
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c49); }
+      }
+
+      return s0;
+    }
+
+    function peg$parseinteger() {
+      var s0, s1, s2;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      s1 = [];
+      if (peg$c54.test(input.charAt(peg$currPos))) {
+        s2 = input.charAt(peg$currPos);
+        peg$currPos++;
+      } else {
+        s2 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c55); }
+      }
+      if (s2 !== peg$FAILED) {
+        while (s2 !== peg$FAILED) {
+          s1.push(s2);
+          if (peg$c54.test(input.charAt(peg$currPos))) {
+            s2 = input.charAt(peg$currPos);
+            peg$currPos++;
           } else {
-            result0 = null;
-            if (reportFailures === 0) {
-              matchFailed("\".\"");
-            }
+            s2 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c55); }
           }
-          if (result0 !== null) {
-            result1 = [];
-            result2 = parse_array_part();
-            if (result2 === null) {
-              result2 = parse_array();
-            }
-            while (result2 !== null) {
-              result1.push(result2);
-              result2 = parse_array_part();
-              if (result2 === null) {
-                result2 = parse_array();
-              }
-            }
-            if (result1 !== null) {
-              result0 = [result0, result1];
-            } else {
-              result0 = null;
-              pos = clone(pos1);
+        }
+      } else {
+        s1 = peg$c3;
+      }
+      if (s1 !== peg$FAILED) {
+        peg$reportedPos = s0;
+        s1 = peg$c56(s1);
+      }
+      s0 = s1;
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c53); }
+      }
+
+      return s0;
+    }
+
+    function peg$parsepath() {
+      var s0, s1, s2, s3;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      s1 = peg$parsekey();
+      if (s1 === peg$FAILED) {
+        s1 = peg$c4;
+      }
+      if (s1 !== peg$FAILED) {
+        s2 = [];
+        s3 = peg$parsearray_part();
+        if (s3 === peg$FAILED) {
+          s3 = peg$parsearray();
+        }
+        if (s3 !== peg$FAILED) {
+          while (s3 !== peg$FAILED) {
+            s2.push(s3);
+            s3 = peg$parsearray_part();
+            if (s3 === peg$FAILED) {
+              s3 = peg$parsearray();
             }
-          } else {
-            result0 = null;
-            pos = clone(pos1);
           }
-          if (result0 !== null) {
-            result0 = (function(offset, line, column, d) {
-              if (d.length > 0) {
-                return [true, d[0]].concat([['line', line], ['col', column]]);
-              }
-              return [true, []].concat([['line', line], ['col', column]]);
-            })(pos0.offset, pos0.line, pos0.column, result0[1]);
-          }
-          if (result0 === null) {
-            pos = clone(pos0);
-          }
-        }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("path");
-        }
-        return result0;
-      }
-      
-      function parse_key() {
-        var result0, result1, result2;
-        var pos0, pos1;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        pos1 = clone(pos);
-        if (/^[a-zA-Z_$]/.test(input.charAt(pos.offset))) {
-          result0 = input.charAt(pos.offset);
-          advance(pos, 1);
         } else {
-          result0 = null;
-          if (reportFailures === 0) {
-            matchFailed("[a-zA-Z_$]");
-          }
+          s2 = peg$c3;
         }
-        if (result0 !== null) {
-          result1 = [];
-          if (/^[0-9a-zA-Z_$\-]/.test(input.charAt(pos.offset))) {
-            result2 = input.charAt(pos.offset);
-            advance(pos, 1);
-          } else {
-            result2 = null;
-            if (reportFailures === 0) {
-              matchFailed("[0-9a-zA-Z_$\\-]");
-            }
-          }
-          while (result2 !== null) {
-            result1.push(result2);
-            if (/^[0-9a-zA-Z_$\-]/.test(input.charAt(pos.offset))) {
-              result2 = input.charAt(pos.offset);
-              advance(pos, 1);
-            } else {
-              result2 = null;
-              if (reportFailures === 0) {
-                matchFailed("[0-9a-zA-Z_$\\-]");
-              }
-            }
-          }
-          if (result1 !== null) {
-            result0 = [result0, result1];
-          } else {
-            result0 = null;
-            pos = clone(pos1);
-          }
+        if (s2 !== peg$FAILED) {
+          peg$reportedPos = s0;
+          s1 = peg$c58(s1, s2);
+          s0 = s1;
         } else {
-          result0 = null;
-          pos = clone(pos1);
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, h, t) { return h + t.join('') })(pos0.offset, pos0.line, pos0.column, result0[0], result0[1]);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("key");
-        }
-        return result0;
-      }
-      
-      function parse_array() {
-        var result0, result1, result2;
-        var pos0, pos1, pos2, pos3, pos4;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        pos1 = clone(pos);
-        pos2 = clone(pos);
-        pos3 = clone(pos);
-        result0 = parse_lb();
-        if (result0 !== null) {
-          pos4 = clone(pos);
-          if (/^[0-9]/.test(input.charAt(pos.offset))) {
-            result2 = input.charAt(pos.offset);
-            advance(pos, 1);
-          } else {
-            result2 = null;
-            if (reportFailures === 0) {
-              matchFailed("[0-9]");
-            }
-          }
-          if (result2 !== null) {
-            result1 = [];
-            while (result2 !== null) {
-              result1.push(result2);
-              if (/^[0-9]/.test(input.charAt(pos.offset))) {
-                result2 = input.charAt(pos.offset);
-                advance(pos, 1);
-              } else {
-                result2 = null;
-                if (reportFailures === 0) {
-                  matchFailed("[0-9]");
-                }
-              }
-            }
-          } else {
-            result1 = null;
-          }
-          if (result1 !== null) {
-            result1 = (function(offset, line, column, n) {return n.join('')})(pos4.offset, pos4.line, pos4.column, result1);
-          }
-          if (result1 === null) {
-            pos = clone(pos4);
-          }
-          if (result1 === null) {
-            result1 = parse_identifier();
-          }
-          if (result1 !== null) {
-            result2 = parse_rb();
-            if (result2 !== null) {
-              result0 = [result0, result1, result2];
-            } else {
-              result0 = null;
-              pos = clone(pos3);
-            }
+          peg$currPos = s0;
+          s0 = peg$c3;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c3;
+      }
+      if (s0 === peg$FAILED) {
+        s0 = peg$currPos;
+        if (input.charCodeAt(peg$currPos) === 46) {
+          s1 = peg$c50;
+          peg$currPos++;
+        } else {
+          s1 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c51); }
+        }
+        if (s1 !== peg$FAILED) {
+          s2 = [];
+          s3 = peg$parsearray_part();
+          if (s3 === peg$FAILED) {
+            s3 = peg$parsearray();
+          }
+          while (s3 !== peg$FAILED) {
+            s2.push(s3);
+            s3 = peg$parsearray_part();
+            if (s3 === peg$FAILED) {
+              s3 = peg$parsearray();
+            }
+          }
+          if (s2 !== peg$FAILED) {
+            peg$reportedPos = s0;
+            s1 = peg$c59(s2);
+            s0 = s1;
           } else {
-            result0 = null;
-            pos = clone(pos3);
+            peg$currPos = s0;
+            s0 = peg$c3;
           }
         } else {
-          result0 = null;
-          pos = clone(pos3);
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, a) {return a; })(pos2.offset, pos2.line, pos2.column, result0[1]);
+          peg$currPos = s0;
+          s0 = peg$c3;
         }
-        if (result0 === null) {
-          pos = clone(pos2);
-        }
-        if (result0 !== null) {
-          result1 = parse_array_part();
-          result1 = result1 !== null ? result1 : "";
-          if (result1 !== null) {
-            result0 = [result0, result1];
+      }
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c57); }
+      }
+
+      return s0;
+    }
+
+    function peg$parsekey() {
+      var s0, s1, s2, s3;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      if (peg$c61.test(input.charAt(peg$currPos))) {
+        s1 = input.charAt(peg$currPos);
+        peg$currPos++;
+      } else {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c62); }
+      }
+      if (s1 !== peg$FAILED) {
+        s2 = [];
+        if (peg$c63.test(input.charAt(peg$currPos))) {
+          s3 = input.charAt(peg$currPos);
+          peg$currPos++;
+        } else {
+          s3 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c64); }
+        }
+        while (s3 !== peg$FAILED) {
+          s2.push(s3);
+          if (peg$c63.test(input.charAt(peg$currPos))) {
+            s3 = input.charAt(peg$currPos);
+            peg$currPos++;
           } else {
-            result0 = null;
-            pos = clone(pos1);
+            s3 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c64); }
           }
+        }
+        if (s2 !== peg$FAILED) {
+          peg$reportedPos = s0;
+          s1 = peg$c65(s1, s2);
+          s0 = s1;
         } else {
-          result0 = null;
-          pos = clone(pos1);
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, i, nk) { if(nk) { nk.unshift(i); } else {nk = [i] } return nk; })(pos0.offset, pos0.line, pos0.column, result0[0], result0[1]);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("array");
-        }
-        return result0;
-      }
-      
-      function parse_array_part() {
-        var result0, result1, result2;
-        var pos0, pos1, pos2, pos3;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        pos1 = clone(pos);
-        pos2 = clone(pos);
-        pos3 = clone(pos);
-        if (input.charCodeAt(pos.offset) === 46) {
-          result1 = ".";
-          advance(pos, 1);
-        } else {
-          result1 = null;
-          if (reportFailures === 0) {
-            matchFailed("\".\"");
-          }
+          peg$currPos = s0;
+          s0 = peg$c3;
         }
-        if (result1 !== null) {
-          result2 = parse_key();
-          if (result2 !== null) {
-            result1 = [result1, result2];
-          } else {
-            result1 = null;
-            pos = clone(pos3);
-          }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c3;
+      }
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c60); }
+      }
+
+      return s0;
+    }
+
+    function peg$parsearray() {
+      var s0, s1, s2, s3, s4, s5;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      s1 = peg$currPos;
+      s2 = peg$parselb();
+      if (s2 !== peg$FAILED) {
+        s3 = peg$currPos;
+        s4 = [];
+        if (peg$c54.test(input.charAt(peg$currPos))) {
+          s5 = input.charAt(peg$currPos);
+          peg$currPos++;
         } else {
-          result1 = null;
-          pos = clone(pos3);
-        }
-        if (result1 !== null) {
-          result1 = (function(offset, line, column, k) {return k})(pos2.offset, pos2.line, pos2.column, result1[1]);
-        }
-        if (result1 === null) {
-          pos = clone(pos2);
-        }
-        if (result1 !== null) {
-          result0 = [];
-          while (result1 !== null) {
-            result0.push(result1);
-            pos2 = clone(pos);
-            pos3 = clone(pos);
-            if (input.charCodeAt(pos.offset) === 46) {
-              result1 = ".";
-              advance(pos, 1);
+          s5 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c55); }
+        }
+        if (s5 !== peg$FAILED) {
+          while (s5 !== peg$FAILED) {
+            s4.push(s5);
+            if (peg$c54.test(input.charAt(peg$currPos))) {
+              s5 = input.charAt(peg$currPos);
+              peg$currPos++;
             } else {
-              result1 = null;
-              if (reportFailures === 0) {
-                matchFailed("\".\"");
-              }
-            }
-            if (result1 !== null) {
-              result2 = parse_key();
-              if (result2 !== null) {
-                result1 = [result1, result2];
-              } else {
-                result1 = null;
-                pos = clone(pos3);
-              }
-            } else {
-              result1 = null;
-              pos = clone(pos3);
-            }
-            if (result1 !== null) {
-              result1 = (function(offset, line, column, k) {return k})(pos2.offset, pos2.line, pos2.column, result1[1]);
-            }
-            if (result1 === null) {
-              pos = clone(pos2);
+              s5 = peg$FAILED;
+              if (peg$silentFails === 0) { peg$fail(peg$c55); }
             }
           }
         } else {
-          result0 = null;
-        }
-        if (result0 !== null) {
-          result1 = parse_array();
-          result1 = result1 !== null ? result1 : "";
-          if (result1 !== null) {
-            result0 = [result0, result1];
+          s4 = peg$c3;
+        }
+        if (s4 !== peg$FAILED) {
+          peg$reportedPos = s3;
+          s4 = peg$c67(s4);
+        }
+        s3 = s4;
+        if (s3 === peg$FAILED) {
+          s3 = peg$parseidentifier();
+        }
+        if (s3 !== peg$FAILED) {
+          s4 = peg$parserb();
+          if (s4 !== peg$FAILED) {
+            peg$reportedPos = s1;
+            s2 = peg$c68(s3);
+            s1 = s2;
           } else {
-            result0 = null;
-            pos = clone(pos1);
+            peg$currPos = s1;
+            s1 = peg$c3;
           }
         } else {
-          result0 = null;
-          pos = clone(pos1);
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, d, a) { if (a) { return d.concat(a); } else { return d; } })(pos0.offset, pos0.line, pos0.column, result0[0], result0[1]);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("array_part");
-        }
-        return result0;
-      }
-      
-      function parse_inline() {
-        var result0, result1, result2;
-        var pos0, pos1;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        pos1 = clone(pos);
-        if (input.charCodeAt(pos.offset) === 34) {
-          result0 = "\"";
-          advance(pos, 1);
+          peg$currPos = s1;
+          s1 = peg$c3;
+        }
+      } else {
+        peg$currPos = s1;
+        s1 = peg$c3;
+      }
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parsearray_part();
+        if (s2 === peg$FAILED) {
+          s2 = peg$c4;
+        }
+        if (s2 !== peg$FAILED) {
+          peg$reportedPos = s0;
+          s1 = peg$c69(s1, s2);
+          s0 = s1;
         } else {
-          result0 = null;
-          if (reportFailures === 0) {
-            matchFailed("\"\\\"\"");
-          }
+          peg$currPos = s0;
+          s0 = peg$c3;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c3;
+      }
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c66); }
+      }
+
+      return s0;
+    }
+
+    function peg$parsearray_part() {
+      var s0, s1, s2, s3, s4;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      s1 = [];
+      s2 = peg$currPos;
+      if (input.charCodeAt(peg$currPos) === 46) {
+        s3 = peg$c50;
+        peg$currPos++;
+      } else {
+        s3 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c51); }
+      }
+      if (s3 !== peg$FAILED) {
+        s4 = peg$parsekey();
+        if (s4 !== peg$FAILED) {
+          peg$reportedPos = s2;
+          s3 = peg$c71(s4);
+          s2 = s3;
+        } else {
+          peg$currPos = s2;
+          s2 = peg$c3;
         }
-        if (result0 !== null) {
-          if (input.charCodeAt(pos.offset) === 34) {
-            result1 = "\"";
-            advance(pos, 1);
+      } else {
+        peg$currPos = s2;
+        s2 = peg$c3;
+      }
+      if (s2 !== peg$FAILED) {
+        while (s2 !== peg$FAILED) {
+          s1.push(s2);
+          s2 = peg$currPos;
+          if (input.charCodeAt(peg$currPos) === 46) {
+            s3 = peg$c50;
+            peg$currPos++;
           } else {
-            result1 = null;
-            if (reportFailures === 0) {
-              matchFailed("\"\\\"\"");
+            s3 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c51); }
+          }
+          if (s3 !== peg$FAILED) {
+            s4 = peg$parsekey();
+            if (s4 !== peg$FAILED) {
+              peg$reportedPos = s2;
+              s3 = peg$c71(s4);
+              s2 = s3;
+            } else {
+              peg$currPos = s2;
+              s2 = peg$c3;
             }
-          }
-          if (result1 !== null) {
-            result0 = [result0, result1];
           } else {
-            result0 = null;
-            pos = clone(pos1);
+            peg$currPos = s2;
+            s2 = peg$c3;
           }
+        }
+      } else {
+        s1 = peg$c3;
+      }
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parsearray();
+        if (s2 === peg$FAILED) {
+          s2 = peg$c4;
+        }
+        if (s2 !== peg$FAILED) {
+          peg$reportedPos = s0;
+          s1 = peg$c72(s1, s2);
+          s0 = s1;
         } else {
-          result0 = null;
-          pos = clone(pos1);
+          peg$currPos = s0;
+          s0 = peg$c3;
         }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column) { return ["literal", ""].concat([['line', line], ['col', column]]) })(pos0.offset, pos0.line, pos0.column);
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c3;
+      }
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c70); }
+      }
+
+      return s0;
+    }
+
+    function peg$parseinline() {
+      var s0, s1, s2, s3;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      if (input.charCodeAt(peg$currPos) === 34) {
+        s1 = peg$c74;
+        peg$currPos++;
+      } else {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c75); }
+      }
+      if (s1 !== peg$FAILED) {
+        if (input.charCodeAt(peg$currPos) === 34) {
+          s2 = peg$c74;
+          peg$currPos++;
+        } else {
+          s2 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c75); }
         }
-        if (result0 === null) {
-          pos = clone(pos0);
+        if (s2 !== peg$FAILED) {
+          peg$reportedPos = s0;
+          s1 = peg$c76();
+          s0 = s1;
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c3;
         }
-        if (result0 === null) {
-          pos0 = clone(pos);
-          pos1 = clone(pos);
-          if (input.charCodeAt(pos.offset) === 34) {
-            result0 = "\"";
-            advance(pos, 1);
-          } else {
-            result0 = null;
-            if (reportFailures === 0) {
-              matchFailed("\"\\\"\"");
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c3;
+      }
+      if (s0 === peg$FAILED) {
+        s0 = peg$currPos;
+        if (input.charCodeAt(peg$currPos) === 34) {
+          s1 = peg$c74;
+          peg$currPos++;
+        } else {
+          s1 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c75); }
+        }
+        if (s1 !== peg$FAILED) {
+          s2 = peg$parseliteral();
+          if (s2 !== peg$FAILED) {
+            if (input.charCodeAt(peg$currPos) === 34) {
+              s3 = peg$c74;
+              peg$currPos++;
+            } else {
+              s3 = peg$FAILED;
+              if (peg$silentFails === 0) { peg$fail(peg$c75); }
             }
-          }
-          if (result0 !== null) {
-            result1 = parse_literal();
-            if (result1 !== null) {
-              if (input.charCodeAt(pos.offset) === 34) {
-                result2 = "\"";
-                advance(pos, 1);
-              } else {
-                result2 = null;
-                if (reportFailures === 0) {
-                  matchFailed("\"\\\"\"");
-                }
-              }
-              if (result2 !== null) {
-                result0 = [result0, result1, result2];
-              } else {
-                result0 = null;
-                pos = clone(pos1);
-              }
+            if (s3 !== peg$FAILED) {
+              peg$reportedPos = s0;
+              s1 = peg$c77(s2);
+              s0 = s1;
             } else {
-              result0 = null;
-              pos = clone(pos1);
+              peg$currPos = s0;
+              s0 = peg$c3;
             }
           } else {
-            result0 = null;
-            pos = clone(pos1);
+            peg$currPos = s0;
+            s0 = peg$c3;
           }
-          if (result0 !== null) {
-            result0 = (function(offset, line, column, l) { return ["literal", l].concat([['line', line], ['col', column]]) })(pos0.offset, pos0.line, pos0.column, result0[1]);
-          }
-          if (result0 === null) {
-            pos = clone(pos0);
-          }
-          if (result0 === null) {
-            pos0 = clone(pos);
-            pos1 = clone(pos);
-            if (input.charCodeAt(pos.offset) === 34) {
-              result0 = "\"";
-              advance(pos, 1);
-            } else {
-              result0 = null;
-              if (reportFailures === 0) {
-                matchFailed("\"\\\"\"");
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c3;
+        }
+        if (s0 === peg$FAILED) {
+          s0 = peg$currPos;
+          if (input.charCodeAt(peg$currPos) === 34) {
+            s1 = peg$c74;
+            peg$currPos++;
+          } else {
+            s1 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c75); }
+          }
+          if (s1 !== peg$FAILED) {
+            s2 = [];
+            s3 = peg$parseinline_part();
+            if (s3 !== peg$FAILED) {
+              while (s3 !== peg$FAILED) {
+                s2.push(s3);
+                s3 = peg$parseinline_part();
               }
+            } else {
+              s2 = peg$c3;
             }
-            if (result0 !== null) {
-              result2 = parse_inline_part();
-              if (result2 !== null) {
-                result1 = [];
-                while (result2 !== null) {
-                  result1.push(result2);
-                  result2 = parse_inline_part();
-                }
+            if (s2 !== peg$FAILED) {
+              if (input.charCodeAt(peg$currPos) === 34) {
+                s3 = peg$c74;
+                peg$currPos++;
               } else {
-                result1 = null;
+                s3 = peg$FAILED;
+                if (peg$silentFails === 0) { peg$fail(peg$c75); }
               }
-              if (result1 !== null) {
-                if (input.charCodeAt(pos.offset) === 34) {
-                  result2 = "\"";
-                  advance(pos, 1);
-                } else {
-                  result2 = null;
-                  if (reportFailures === 0) {
-                    matchFailed("\"\\\"\"");
-                  }
-                }
-                if (result2 !== null) {
-                  result0 = [result0, result1, result2];
-                } else {
-                  result0 = null;
-                  pos = clone(pos1);
-                }
+              if (s3 !== peg$FAILED) {
+                peg$reportedPos = s0;
+                s1 = peg$c78(s2);
+                s0 = s1;
               } else {
-                result0 = null;
-                pos = clone(pos1);
+                peg$currPos = s0;
+                s0 = peg$c3;
               }
             } else {
-              result0 = null;
-              pos = clone(pos1);
-            }
-            if (result0 !== null) {
-              result0 = (function(offset, line, column, p) { return ["body"].concat(p).concat([['line', line], ['col', column]]) })(pos0.offset, pos0.line, pos0.column, result0[1]);
-            }
-            if (result0 === null) {
-              pos = clone(pos0);
+              peg$currPos = s0;
+              s0 = peg$c3;
             }
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c3;
           }
         }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("inline");
-        }
-        return result0;
-      }
-      
-      function parse_inline_part() {
-        var result0;
-        var pos0;
-        
-        result0 = parse_special();
-        if (result0 === null) {
-          result0 = parse_reference();
-          if (result0 === null) {
-            pos0 = clone(pos);
-            result0 = parse_literal();
-            if (result0 !== null) {
-              result0 = (function(offset, line, column, l) { return ["buffer", l] })(pos0.offset, pos0.line, pos0.column, result0);
-            }
-            if (result0 === null) {
-              pos = clone(pos0);
-            }
-          }
+      }
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c73); }
+      }
+
+      return s0;
+    }
+
+    function peg$parseinline_part() {
+      var s0, s1;
+
+      s0 = peg$parsespecial();
+      if (s0 === peg$FAILED) {
+        s0 = peg$parsereference();
+        if (s0 === peg$FAILED) {
+          s0 = peg$currPos;
+          s1 = peg$parseliteral();
+          if (s1 !== peg$FAILED) {
+            peg$reportedPos = s0;
+            s1 = peg$c79(s1);
+          }
+          s0 = s1;
+        }
+      }
+
+      return s0;
+    }
+
+    function peg$parsebuffer() {
+      var s0, s1, s2, s3, s4, s5, s6, s7;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      s1 = peg$parseeol();
+      if (s1 !== peg$FAILED) {
+        s2 = [];
+        s3 = peg$parsews();
+        while (s3 !== peg$FAILED) {
+          s2.push(s3);
+          s3 = peg$parsews();
+        }
+        if (s2 !== peg$FAILED) {
+          peg$reportedPos = s0;
+          s1 = peg$c81(s1, s2);
+          s0 = s1;
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c3;
         }
-        return result0;
-      }
-      
-      function parse_buffer() {
-        var result0, result1, result2, result3, result4, result5;
-        var pos0, pos1, pos2, pos3;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        pos1 = clone(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 {
-            result0 = null;
-            pos = clone(pos1);
-          }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c3;
+      }
+      if (s0 === peg$FAILED) {
+        s0 = peg$currPos;
+        s1 = [];
+        s2 = peg$currPos;
+        s3 = peg$currPos;
+        peg$silentFails++;
+        s4 = peg$parsetag();
+        peg$silentFails--;
+        if (s4 === peg$FAILED) {
+          s3 = peg$c6;
         } else {
-          result0 = null;
-          pos = clone(pos1);
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, e, w) { return ["format", e, w.join('')].concat([['line', line], ['col', column]]) })(pos0.offset, pos0.line, pos0.column, result0[0], result0[1]);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        if (result0 === null) {
-          pos0 = clone(pos);
-          pos1 = clone(pos);
-          pos2 = clone(pos);
-          pos3 = clone(pos);
-          reportFailures++;
-          result1 = parse_tag();
-          reportFailures--;
-          if (result1 === null) {
-            result1 = "";
+          peg$currPos = s3;
+          s3 = peg$c3;
+        }
+        if (s3 !== peg$FAILED) {
+          s4 = peg$currPos;
+          peg$silentFails++;
+          s5 = peg$parseraw();
+          peg$silentFails--;
+          if (s5 === peg$FAILED) {
+            s4 = peg$c6;
           } else {
-            result1 = null;
-            pos = clone(pos3);
-          }
-          if (result1 !== null) {
-            pos3 = clone(pos);
-            reportFailures++;
-            result2 = parse_raw();
-            reportFailures--;
-            if (result2 === null) {
-              result2 = "";
+            peg$currPos = s4;
+            s4 = peg$c3;
+          }
+          if (s4 !== peg$FAILED) {
+            s5 = peg$currPos;
+            peg$silentFails++;
+            s6 = peg$parsecomment();
+            peg$silentFails--;
+            if (s6 === peg$FAILED) {
+              s5 = peg$c6;
             } else {
-              result2 = null;
-              pos = clone(pos3);
-            }
-            if (result2 !== null) {
-              pos3 = clone(pos);
-              reportFailures++;
-              result3 = parse_comment();
-              reportFailures--;
-              if (result3 === null) {
-                result3 = "";
+              peg$currPos = s5;
+              s5 = peg$c3;
+            }
+            if (s5 !== peg$FAILED) {
+              s6 = peg$currPos;
+              peg$silentFails++;
+              s7 = peg$parseeol();
+              peg$silentFails--;
+              if (s7 === peg$FAILED) {
+                s6 = peg$c6;
               } else {
-                result3 = null;
-                pos = clone(pos3);
+                peg$currPos = s6;
+                s6 = peg$c3;
               }
-              if (result3 !== null) {
-                pos3 = clone(pos);
-                reportFailures++;
-                result4 = parse_eol();
-                reportFailures--;
-                if (result4 === null) {
-                  result4 = "";
+              if (s6 !== peg$FAILED) {
+                if (input.length > peg$currPos) {
+                  s7 = input.charAt(peg$currPos);
+                  peg$currPos++;
                 } else {
-                  result4 = null;
-                  pos = clone(pos3);
+                  s7 = peg$FAILED;
+                  if (peg$silentFails === 0) { peg$fail(peg$c82); }
                 }
-                if (result4 !== null) {
-                  if (input.length > pos.offset) {
-                    result5 = input.charAt(pos.offset);
-                    advance(pos, 1);
-                  } else {
-                    result5 = null;
-                    if (reportFailures === 0) {
-                      matchFailed("any character");
-                    }
-                  }
-                  if (result5 !== null) {
-                    result1 = [result1, result2, result3, result4, result5];
-                  } else {
-                    result1 = null;
-                    pos = clone(pos2);
-                  }
+                if (s7 !== peg$FAILED) {
+                  peg$reportedPos = s2;
+                  s3 = peg$c83(s7);
+                  s2 = s3;
                 } else {
-                  result1 = null;
-                  pos = clone(pos2);
+                  peg$currPos = s2;
+                  s2 = peg$c3;
                 }
               } else {
-                result1 = null;
-                pos = clone(pos2);
+                peg$currPos = s2;
+                s2 = peg$c3;
               }
             } else {
-              result1 = null;
-              pos = clone(pos2);
+              peg$currPos = s2;
+              s2 = peg$c3;
             }
           } else {
-            result1 = null;
-            pos = clone(pos2);
-          }
-          if (result1 !== null) {
-            result1 = (function(offset, line, column, c) {return c})(pos1.offset, pos1.line, pos1.column, result1[4]);
-          }
-          if (result1 === null) {
-            pos = clone(pos1);
-          }
-          if (result1 !== null) {
-            result0 = [];
-            while (result1 !== null) {
-              result0.push(result1);
-              pos1 = clone(pos);
-              pos2 = clone(pos);
-              pos3 = clone(pos);
-              reportFailures++;
-              result1 = parse_tag();
-              reportFailures--;
-              if (result1 === null) {
-                result1 = "";
+            peg$currPos = s2;
+            s2 = peg$c3;
+          }
+        } else {
+          peg$currPos = s2;
+          s2 = peg$c3;
+        }
+        if (s2 !== peg$FAILED) {
+          while (s2 !== peg$FAILED) {
+            s1.push(s2);
+            s2 = peg$currPos;
+            s3 = peg$currPos;
+            peg$silentFails++;
+            s4 = peg$parsetag();
+            peg$silentFails--;
+            if (s4 === peg$FAILED) {
+              s3 = peg$c6;
+            } else {
+              peg$currPos = s3;
+              s3 = peg$c3;
+            }
+            if (s3 !== peg$FAILED) {
+              s4 = peg$currPos;
+              peg$silentFails++;
+              s5 = peg$parseraw();
+              peg$silentFails--;
+              if (s5 === peg$FAILED) {
+                s4 = peg$c6;
               } else {
-                result1 = null;
-                pos = clone(pos3);
+                peg$currPos = s4;
+                s4 = peg$c3;
               }
-              if (result1 !== null) {
-                pos3 = clone(pos);
-                reportFailures++;
-                result2 = parse_raw();
-                reportFailures--;
-                if (result2 === null) {
-                  result2 = "";
+              if (s4 !== peg$FAILED) {
+                s5 = peg$currPos;
+                peg$silentFails++;
+                s6 = peg$parsecomment();
+                peg$silentFails--;
+                if (s6 === peg$FAILED) {
+                  s5 = peg$c6;
                 } else {
-                  result2 = null;
-                  pos = clone(pos3);
+                  peg$currPos = s5;
+                  s5 = peg$c3;
                 }
-                if (result2 !== null) {
-                  pos3 = clone(pos);
-                  reportFailures++;
-                  result3 = parse_comment();
-                  reportFailures--;
-                  if (result3 === null) {
-                    result3 = "";
+                if (s5 !== peg$FAILED) {
+                  s6 = peg$currPos;
+                  peg$silentFails++;
+                  s7 = peg$parseeol();
+                  peg$silentFails--;
+                  if (s7 === peg$FAILED) {
+                    s6 = peg$c6;
                   } else {
-                    result3 = null;
-                    pos = clone(pos3);
+                    peg$currPos = s6;
+                    s6 = peg$c3;
                   }
-                  if (result3 !== null) {
-                    pos3 = clone(pos);
-                    reportFailures++;
-                    result4 = parse_eol();
-                    reportFailures--;
-                    if (result4 === null) {
-                      result4 = "";
+                  if (s6 !== peg$FAILED) {
+                    if (input.length > peg$currPos) {
+                      s7 = input.charAt(peg$currPos);
+                      peg$currPos++;
                     } else {
-                      result4 = null;
-                      pos = clone(pos3);
+                      s7 = peg$FAILED;
+                      if (peg$silentFails === 0) { peg$fail(peg$c82); }
                     }
-                    if (result4 !== null) {
-                      if (input.length > pos.offset) {
-                        result5 = input.charAt(pos.offset);
-                        advance(pos, 1);
-                      } else {
-                        result5 = null;
-                        if (reportFailures === 0) {
-                          matchFailed("any character");
-                        }
-                      }
-                      if (result5 !== null) {
-                        result1 = [result1, result2, result3, result4, result5];
-                      } else {
-                        result1 = null;
-                        pos = clone(pos2);
-                      }
+                    if (s7 !== peg$FAILED) {
+                      peg$reportedPos = s2;
+                      s3 = peg$c83(s7);
+                      s2 = s3;
                     } else {
-                      result1 = null;
-                      pos = clone(pos2);
+                      peg$currPos = s2;
+                      s2 = peg$c3;
                     }
                   } else {
-                    result1 = null;
-                    pos = clone(pos2);
+                    peg$currPos = s2;
+                    s2 = peg$c3;
                   }
                 } else {
-                  result1 = null;
-                  pos = clone(pos2);
+                  peg$currPos = s2;
+                  s2 = peg$c3;
                 }
               } else {
-                result1 = null;
-                pos = clone(pos2);
-              }
-              if (result1 !== null) {
-                result1 = (function(offset, line, column, c) {return c})(pos1.offset, pos1.line, pos1.column, result1[4]);
+                peg$currPos = s2;
+                s2 = peg$c3;
               }
-              if (result1 === null) {
-                pos = clone(pos1);
-              }
-            }
-          } else {
-            result0 = null;
-          }
-          if (result0 !== null) {
-            result0 = (function(offset, line, column, b) { return ["buffer", b.join('')].concat([['line', line], ['col', column]]) })(pos0.offset, pos0.line, pos0.column, result0);
-          }
-          if (result0 === null) {
-            pos = clone(pos0);
-          }
-        }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("buffer");
-        }
-        return result0;
-      }
-      
-      function parse_literal() {
-        var result0, result1, result2;
-        var pos0, pos1, pos2, pos3;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        pos1 = clone(pos);
-        pos2 = clone(pos);
-        pos3 = clone(pos);
-        reportFailures++;
-        result1 = parse_tag();
-        reportFailures--;
-        if (result1 === null) {
-          result1 = "";
-        } else {
-          result1 = null;
-          pos = clone(pos3);
-        }
-        if (result1 !== null) {
-          result2 = parse_esc();
-          if (result2 === null) {
-            if (/^[^"]/.test(input.charAt(pos.offset))) {
-              result2 = input.charAt(pos.offset);
-              advance(pos, 1);
             } else {
-              result2 = null;
-              if (reportFailures === 0) {
-                matchFailed("[^\"]");
-              }
+              peg$currPos = s2;
+              s2 = peg$c3;
             }
           }
-          if (result2 !== null) {
-            result1 = [result1, result2];
+        } else {
+          s1 = peg$c3;
+        }
+        if (s1 !== peg$FAILED) {
+          peg$reportedPos = s0;
+          s1 = peg$c84(s1);
+        }
+        s0 = s1;
+      }
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c80); }
+      }
+
+      return s0;
+    }
+
+    function peg$parseliteral() {
+      var s0, s1, s2, s3, s4;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      s1 = [];
+      s2 = peg$currPos;
+      s3 = peg$currPos;
+      peg$silentFails++;
+      s4 = peg$parsetag();
+      peg$silentFails--;
+      if (s4 === peg$FAILED) {
+        s3 = peg$c6;
+      } else {
+        peg$currPos = s3;
+        s3 = peg$c3;
+      }
+      if (s3 !== peg$FAILED) {
+        s4 = peg$parseesc();
+        if (s4 === peg$FAILED) {
+          if (peg$c86.test(input.charAt(peg$currPos))) {
+            s4 = input.charAt(peg$currPos);
+            peg$currPos++;
           } else {
-            result1 = null;
-            pos = clone(pos2);
+            s4 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c87); }
           }
+        }
+        if (s4 !== peg$FAILED) {
+          peg$reportedPos = s2;
+          s3 = peg$c83(s4);
+          s2 = s3;
         } else {
-          result1 = null;
-          pos = clone(pos2);
-        }
-        if (result1 !== null) {
-          result1 = (function(offset, line, column, c) {return c})(pos1.offset, pos1.line, pos1.column, result1[1]);
-        }
-        if (result1 === null) {
-          pos = clone(pos1);
-        }
-        if (result1 !== null) {
-          result0 = [];
-          while (result1 !== null) {
-            result0.push(result1);
-            pos1 = clone(pos);
-            pos2 = clone(pos);
-            pos3 = clone(pos);
-            reportFailures++;
-            result1 = parse_tag();
-            reportFailures--;
-            if (result1 === null) {
-              result1 = "";
-            } else {
-              result1 = null;
-              pos = clone(pos3);
-            }
-            if (result1 !== null) {
-              result2 = parse_esc();
-              if (result2 === null) {
-                if (/^[^"]/.test(input.charAt(pos.offset))) {
-                  result2 = input.charAt(pos.offset);
-                  advance(pos, 1);
-                } else {
-                  result2 = null;
-                  if (reportFailures === 0) {
-                    matchFailed("[^\"]");
-                  }
-                }
-              }
-              if (result2 !== null) {
-                result1 = [result1, result2];
+          peg$currPos = s2;
+          s2 = peg$c3;
+        }
+      } else {
+        peg$currPos = s2;
+        s2 = peg$c3;
+      }
+      if (s2 !== peg$FAILED) {
+        while (s2 !== peg$FAILED) {
+          s1.push(s2);
+          s2 = peg$currPos;
+          s3 = peg$currPos;
+          peg$silentFails++;
+          s4 = peg$parsetag();
+          peg$silentFails--;
+          if (s4 === peg$FAILED) {
+            s3 = peg$c6;
+          } else {
+            peg$currPos = s3;
+            s3 = peg$c3;
+          }
+          if (s3 !== peg$FAILED) {
+            s4 = peg$parseesc();
+            if (s4 === peg$FAILED) {
+              if (peg$c86.test(input.charAt(peg$currPos))) {
+                s4 = input.charAt(peg$currPos);
+                peg$currPos++;
               } else {
-                result1 = null;
-                pos = clone(pos2);
+                s4 = peg$FAILED;
+                if (peg$silentFails === 0) { peg$fail(peg$c87); }
               }
-            } else {
-              result1 = null;
-              pos = clone(pos2);
             }
-            if (result1 !== null) {
-              result1 = (function(offset, line, column, c) {return c})(pos1.offset, pos1.line, pos1.column, result1[1]);
-            }
-            if (result1 === null) {
-              pos = clone(pos1);
+            if (s4 !== peg$FAILED) {
+              peg$reportedPos = s2;
+              s3 = peg$c83(s4);
+              s2 = s3;
+            } else {
+              peg$currPos = s2;
+              s2 = peg$c3;
             }
+          } else {
+            peg$currPos = s2;
+            s2 = peg$c3;
           }
-        } else {
-          result0 = null;
         }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, b) { return b.join('') })(pos0.offset, pos0.line, pos0.column, result0);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("literal");
-        }
-        return result0;
+      } else {
+        s1 = peg$c3;
       }
-      
-      function parse_esc() {
-        var result0;
-        var pos0;
-        
-        pos0 = clone(pos);
-        if (input.substr(pos.offset, 2) === "\\\"") {
-          result0 = "\\\"";
-          advance(pos, 2);
+      if (s1 !== peg$FAILED) {
+        peg$reportedPos = s0;
+        s1 = peg$c88(s1);
+      }
+      s0 = s1;
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c85); }
+      }
+
+      return s0;
+    }
+
+    function peg$parseesc() {
+      var s0, s1;
+
+      s0 = peg$currPos;
+      if (input.substr(peg$currPos, 2) === peg$c89) {
+        s1 = peg$c89;
+        peg$currPos += 2;
+      } else {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c90); }
+      }
+      if (s1 !== peg$FAILED) {
+        peg$reportedPos = s0;
+        s1 = peg$c91();
+      }
+      s0 = s1;
+
+      return s0;
+    }
+
+    function peg$parseraw() {
+      var s0, s1, s2, s3, s4, s5;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      if (input.substr(peg$currPos, 2) === peg$c93) {
+        s1 = peg$c93;
+        peg$currPos += 2;
+      } else {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c94); }
+      }
+      if (s1 !== peg$FAILED) {
+        s2 = [];
+        s3 = peg$currPos;
+        s4 = peg$currPos;
+        peg$silentFails++;
+        if (input.substr(peg$currPos, 2) === peg$c95) {
+          s5 = peg$c95;
+          peg$currPos += 2;
         } else {
-          result0 = null;
-          if (reportFailures === 0) {
-            matchFailed("\"\\\\\\\"\"");
-          }
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column) { return '"' })(pos0.offset, pos0.line, pos0.column);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        return result0;
-      }
-      
-      function parse_raw() {
-        var result0, result1, result2, result3;
-        var pos0, pos1, pos2, pos3, pos4;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        pos1 = clone(pos);
-        if (input.substr(pos.offset, 2) === "{`") {
-          result0 = "{`";
-          advance(pos, 2);
+          s5 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c96); }
+        }
+        peg$silentFails--;
+        if (s5 === peg$FAILED) {
+          s4 = peg$c6;
         } else {
-          result0 = null;
-          if (reportFailures === 0) {
-            matchFailed("\"{`\"");
-          }
-        }
-        if (result0 !== null) {
-          result1 = [];
-          pos2 = clone(pos);
-          pos3 = clone(pos);
-          pos4 = clone(pos);
-          reportFailures++;
-          if (input.substr(pos.offset, 2) === "`}") {
-            result2 = "`}";
-            advance(pos, 2);
+          peg$currPos = s4;
+          s4 = peg$c3;
+        }
+        if (s4 !== peg$FAILED) {
+          if (input.length > peg$currPos) {
+            s5 = input.charAt(peg$currPos);
+            peg$currPos++;
           } else {
-            result2 = null;
-            if (reportFailures === 0) {
-              matchFailed("\"`}\"");
-            }
+            s5 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c82); }
           }
-          reportFailures--;
-          if (result2 === null) {
-            result2 = "";
+          if (s5 !== peg$FAILED) {
+            peg$reportedPos = s3;
+            s4 = peg$c97(s5);
+            s3 = s4;
           } else {
-            result2 = null;
-            pos = clone(pos4);
+            peg$currPos = s3;
+            s3 = peg$c3;
           }
-          if (result2 !== null) {
-            if (input.length > pos.offset) {
-              result3 = input.charAt(pos.offset);
-              advance(pos, 1);
-            } else {
-              result3 = null;
-              if (reportFailures === 0) {
-                matchFailed("any character");
-              }
-            }
-            if (result3 !== null) {
-              result2 = [result2, result3];
-            } else {
-              result2 = null;
-              pos = clone(pos3);
-            }
+        } else {
+          peg$currPos = s3;
+          s3 = peg$c3;
+        }
+        while (s3 !== peg$FAILED) {
+          s2.push(s3);
+          s3 = peg$currPos;
+          s4 = peg$currPos;
+          peg$silentFails++;
+          if (input.substr(peg$currPos, 2) === peg$c95) {
+            s5 = peg$c95;
+            peg$currPos += 2;
           } else {
-            result2 = null;
-            pos = clone(pos3);
-          }
-          if (result2 !== null) {
-            result2 = (function(offset, line, column, char) {return char})(pos2.offset, pos2.line, pos2.column, result2[1]);
-          }
-          if (result2 === null) {
-            pos = clone(pos2);
-          }
-          while (result2 !== null) {
-            result1.push(result2);
-            pos2 = clone(pos);
-            pos3 = clone(pos);
-            pos4 = clone(pos);
-            reportFailures++;
-            if (input.substr(pos.offset, 2) === "`}") {
-              result2 = "`}";
-              advance(pos, 2);
-            } else {
-              result2 = null;
-              if (reportFailures === 0) {
-                matchFailed("\"`}\"");
-              }
-            }
-            reportFailures--;
-            if (result2 === null) {
-              result2 = "";
-            } else {
-              result2 = null;
-              pos = clone(pos4);
-            }
-            if (result2 !== null) {
-              if (input.length > pos.offset) {
-                result3 = input.charAt(pos.offset);
-                advance(pos, 1);
-              } else {
-                result3 = null;
-                if (reportFailures === 0) {
-                  matchFailed("any character");
-                }
-              }
-              if (result3 !== null) {
-                result2 = [result2, result3];
-              } else {
-                result2 = null;
-                pos = clone(pos3);
-              }
-            } else {
-              result2 = null;
-              pos = clone(pos3);
-            }
-            if (result2 !== null) {
-              result2 = (function(offset, line, column, char) {return char})(pos2.offset, pos2.line, pos2.column, result2[1]);
-            }
-            if (result2 === null) {
-              pos = clone(pos2);
-            }
+            s5 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c96); }
+          }
+          peg$silentFails--;
+          if (s5 === peg$FAILED) {
+            s4 = peg$c6;
+          } else {
+            peg$currPos = s4;
+            s4 = peg$c3;
           }
-          if (result1 !== null) {
-            if (input.substr(pos.offset, 2) === "`}") {
-              result2 = "`}";
-              advance(pos, 2);
+          if (s4 !== peg$FAILED) {
+            if (input.length > peg$currPos) {
+              s5 = input.charAt(peg$currPos);
+              peg$currPos++;
             } else {
-              result2 = null;
-              if (reportFailures === 0) {
-                matchFailed("\"`}\"");
-              }
+              s5 = peg$FAILED;
+              if (peg$silentFails === 0) { peg$fail(peg$c82); }
             }
-            if (result2 !== null) {
-              result0 = [result0, result1, result2];
+            if (s5 !== peg$FAILED) {
+              peg$reportedPos = s3;
+              s4 = peg$c97(s5);
+              s3 = s4;
             } else {
-              result0 = null;
-              pos = clone(pos1);
+              peg$currPos = s3;
+              s3 = peg$c3;
             }
           } else {
-            result0 = null;
-            pos = clone(pos1);
+            peg$currPos = s3;
+            s3 = peg$c3;
+          }
+        }
+        if (s2 !== peg$FAILED) {
+          if (input.substr(peg$currPos, 2) === peg$c95) {
+            s3 = peg$c95;
+            peg$currPos += 2;
+          } else {
+            s3 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c96); }
           }
+          if (s3 !== peg$FAILED) {
+            peg$reportedPos = s0;
+            s1 = peg$c98(s2);
+            s0 = s1;
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c3;
+          }
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c3;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c3;
+      }
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c92); }
+      }
+
+      return s0;
+    }
+
+    function peg$parsecomment() {
+      var s0, s1, s2, s3, s4, s5;
+
+      peg$silentFails++;
+      s0 = peg$currPos;
+      if (input.substr(peg$currPos, 2) === peg$c100) {
+        s1 = peg$c100;
+        peg$currPos += 2;
+      } else {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c101); }
+      }
+      if (s1 !== peg$FAILED) {
+        s2 = [];
+        s3 = peg$currPos;
+        s4 = peg$currPos;
+        peg$silentFails++;
+        if (input.substr(peg$currPos, 2) === peg$c102) {
+          s5 = peg$c102;
+          peg$currPos += 2;
         } else {
-          result0 = null;
-          pos = clone(pos1);
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, rawText) { return ["raw", rawText.join('')].concat([['line', line], ['col', column]]) })(pos0.offset, pos0.line, pos0.column, result0[1]);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("raw");
-        }
-        return result0;
-      }
-      
-      function parse_comment() {
-        var result0, result1, result2, result3;
-        var pos0, pos1, pos2, pos3, pos4;
-        
-        reportFailures++;
-        pos0 = clone(pos);
-        pos1 = clone(pos);
-        if (input.substr(pos.offset, 2) === "{!") {
-          result0 = "{!";
-          advance(pos, 2);
+          s5 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c103); }
+        }
+        peg$silentFails--;
+        if (s5 === peg$FAILED) {
+          s4 = peg$c6;
         } else {
-          result0 = null;
-          if (reportFailures === 0) {
-            matchFailed("\"{!\"");
-          }
-        }
-        if (result0 !== null) {
-          result1 = [];
-          pos2 = clone(pos);
-          pos3 = clone(pos);
-          pos4 = clone(pos);
-          reportFailures++;
-          if (input.substr(pos.offset, 2) === "!}") {
-            result2 = "!}";
-            advance(pos, 2);
+          peg$currPos = s4;
+          s4 = peg$c3;
+        }
+        if (s4 !== peg$FAILED) {
+          if (input.length > peg$currPos) {
+            s5 = input.charAt(peg$currPos);
+            peg$currPos++;
           } else {
-            result2 = null;
-            if (reportFailures === 0) {
-              matchFailed("\"!}\"");
-            }
+            s5 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c82); }
           }
-          reportFailures--;
-          if (result2 === null) {
-            result2 = "";
+          if (s5 !== peg$FAILED) {
+            peg$reportedPos = s3;
+            s4 = peg$c83(s5);
+            s3 = s4;
           } else {
-            result2 = null;
-            pos = clone(pos4);
+            peg$currPos = s3;
+            s3 = peg$c3;
           }
-          if (result2 !== null) {
-            if (input.length > pos.offset) {
-              result3 = input.charAt(pos.offset);
-              advance(pos, 1);
-            } else {
-              result3 = null;
-              if (reportFailures === 0) {
-                matchFailed("any character");
-              }
-            }
-            if (result3 !== null) {
-              result2 = [result2, result3];
-            } else {
-              result2 = null;
-              pos = clone(pos3);
-            }
+        } else {
+          peg$currPos = s3;
+          s3 = peg$c3;
+        }
+        while (s3 !== peg$FAILED) {
+          s2.push(s3);
+          s3 = peg$currPos;
+          s4 = peg$currPos;
+          peg$silentFails++;
+          if (input.substr(peg$currPos, 2) === peg$c102) {
+            s5 = peg$c102;
+            peg$currPos += 2;
           } else {
-            result2 = null;
-            pos = clone(pos3);
-          }
-          if (result2 !== null) {
-            result2 = (function(offset, line, column, c) {return c})(pos2.offset, pos2.line, pos2.column, result2[1]);
-          }
-          if (result2 === null) {
-            pos = clone(pos2);
-          }
-          while (result2 !== null) {
-            result1.push(result2);
-            pos2 = clone(pos);
-            pos3 = clone(pos);
-            pos4 = clone(pos);
-            reportFailures++;
-            if (input.substr(pos.offset, 2) === "!}") {
-              result2 = "!}";
-              advance(pos, 2);
-            } else {
-              result2 = null;
-              if (reportFailures === 0) {
-                matchFailed("\"!}\"");
-              }
-            }
-            reportFailures--;
-            if (result2 === null) {
-              result2 = "";
-            } else {
-              result2 = null;
-              pos = clone(pos4);
-            }
-            if (result2 !== null) {
-              if (input.length > pos.offset) {
-                result3 = input.charAt(pos.offset);
-                advance(pos, 1);
-              } else {
-                result3 = null;
-                if (reportFailures === 0) {
-                  matchFailed("any character");
-                }
-              }
-              if (result3 !== null) {
-                result2 = [result2, result3];
-              } else {
-                result2 = null;
-                pos = clone(pos3);
-              }
-            } else {
-              result2 = null;
-              pos = clone(pos3);
-            }
-            if (result2 !== null) {
-              result2 = (function(offset, line, column, c) {return c})(pos2.offset, pos2.line, pos2.column, result2[1]);
-            }
-            if (result2 === null) {
-              pos = clone(pos2);
-            }
+            s5 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c103); }
           }
-          if (result1 !== null) {
-            if (input.substr(pos.offset, 2) === "!}") {
-              result2 = "!}";
-              advance(pos, 2);
+          peg$silentFails--;
+          if (s5 === peg$FAILED) {
+            s4 = peg$c6;
+          } else {
+            peg$currPos = s4;
+            s4 = peg$c3;
+          }
+          if (s4 !== peg$FAILED) {
+            if (input.length > peg$currPos) {
+              s5 = input.charAt(peg$currPos);
+              peg$currPos++;
             } else {
-              result2 = null;
-              if (reportFailures === 0) {
-                matchFailed("\"!}\"");
-              }
+              s5 = peg$FAILED;
+              if (peg$silentFails === 0) { peg$fail(peg$c82); }
             }
-            if (result2 !== null) {
-              result0 = [result0, result1, result2];
+            if (s5 !== peg$FAILED) {
+              peg$reportedPos = s3;
+              s4 = peg$c83(s5);
+              s3 = s4;
             } else {
-              result0 = null;
-              pos = clone(pos1);
+              peg$currPos = s3;
+              s3 = peg$c3;
             }
           } else {
-            result0 = null;
-            pos = clone(pos1);
+            peg$currPos = s3;
+            s3 = peg$c3;
+          }
+        }
+        if (s2 !== peg$FAILED) {
+          if (input.substr(peg$currPos, 2) === peg$c102) {
+            s3 = peg$c102;
+            peg$currPos += 2;
+          } else {
+            s3 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c103); }
+          }
+          if (s3 !== peg$FAILED) {
+            peg$reportedPos = s0;
+            s1 = peg$c104(s2);
+            s0 = s1;
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c3;
           }
         } else {
-          result0 = null;
-          pos = clone(pos1);
-        }
-        if (result0 !== null) {
-          result0 = (function(offset, line, column, c) { return ["comment", c.join('')].concat([['line', line], ['col', column]]) })(pos0.offset, pos0.line, pos0.column, result0[1]);
-        }
-        if (result0 === null) {
-          pos = clone(pos0);
-        }
-        reportFailures--;
-        if (reportFailures === 0 && result0 === null) {
-          matchFailed("comment");
-        }
-        return result0;
-      }
-      
-      function parse_tag() {
-        var result0, result1, result2, result3, result4, result5, result6, result7;
-        var pos0, pos1, pos2;
-        
-        pos0 = clone(pos);
-        result0 = parse_ld();
-        if (result0 !== null) {
-          result1 = [];
-          result2 = parse_ws();
-          while (result2 !== null) {
-            result1.push(result2);
-            result2 = parse_ws();
-          }
-          if (result1 !== null) {
-            if (/^[#?^><+%:@\/~%]/.test(input.charAt(pos.offset))) {
-              result2 = input.charAt(pos.offset);
-              advance(pos, 1);
-            } else {
-              result2 = null;
-              if (reportFailures === 0) {
-                matchFailed("[#?^><+%:@\\/~%]");
-              }
-            }
-            if (result2 !== null) {
-              result3 = [];
-              result4 = parse_ws();
-              while (result4 !== null) {
-                result3.push(result4);
-                result4 = parse_ws();
+          peg$currPos = s0;
+          s0 = peg$c3;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c3;
+      }
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c99); }
+      }
+
+      return s0;
+    }
+
+    function peg$parsetag() {
+      var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;
+
+      s0 = peg$currPos;
+      s1 = peg$parseld();
+      if (s1 !== peg$FAILED) {
+        s2 = [];
+        s3 = peg$parsews();
+        while (s3 !== peg$FAILED) {
+          s2.push(s3);
+          s3 = peg$parsews();
+        }
+        if (s2 !== peg$FAILED) {
+          if (peg$c105.test(input.charAt(peg$currPos))) {
+            s3 = input.charAt(peg$currPos);
+            peg$currPos++;
+          } else {
+            s3 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c106); }
+          }
+          if (s3 !== peg$FAILED) {
+            s4 = [];
+            s5 = peg$parsews();
+            while (s5 !== peg$FAILED) {
+              s4.push(s5);
+              s5 = peg$parsews();
+            }
+            if (s4 !== peg$FAILED) {
+              s5 = [];
+              s6 = peg$currPos;
+              s7 = peg$currPos;
+              peg$silentFails++;
+              s8 = peg$parserd();
+              peg$silentFails--;
+              if (s8 === peg$FAILED) {
+                s7 = peg$c6;
+              } else {
+                peg$currPos = s7;
+                s7 = peg$c3;
               }
-              if (result3 !== null) {
-                pos1 = clone(pos);
-                pos2 = clone(pos);
-                reportFailures++;
-                result5 = parse_rd();
-                reportFailures--;
-                if (result5 === null) {
-                  result5 = "";
+              if (s7 !== peg$FAILED) {
+                s8 = peg$currPos;
+                peg$silentFails++;
+                s9 = peg$parseeol();
+                peg$silentFails--;
+                if (s9 === peg$FAILED) {
+                  s8 = peg$c6;
                 } else {
-                  result5 = null;
-                  pos = clone(pos2);
+                  peg$currPos = s8;
+                  s8 = peg$c3;
                 }
-                if (result5 !== null) {
-                  pos2 = clone(pos);
-                  reportFailures++;
-                  result6 = parse_eol();
-                  reportFailures--;
-                  if (result6 === null) {
-                    result6 = "";
+                if (s8 !== peg$FAILED) {
+                  if (input.length > peg$currPos) {
+                    s9 = input.charAt(peg$currPos);
+                    peg$currPos++;
                   } else {
-                    result6 = null;
-                    pos = clone(pos2);
+                    s9 = peg$FAILED;
+                    if (peg$silentFails === 0) { peg$fail(peg$c82); }
                   }
-                  if (result6 !== null) {
-                    if (input.length > pos.offset) {
-                      result7 = input.charAt(pos.offset);
-                      advance(pos, 1);
-                    } else {
-                      result7 = null;
-                      if (reportFailures === 0) {
-                        matchFailed("any character");
-                      }
-                    }
-                    if (result7 !== null) {
-                      result5 = [result5, result6, result7];
-                    } else {
-                      result5 = null;
-                      pos = clone(pos1);
-                    }
+                  if (s9 !== peg$FAILED) {
+                    s7 = [s7, s8, s9];
+                    s6 = s7;
                   } else {
-                    result5 = null;
-                    pos = clone(pos1);
+                    peg$currPos = s6;
+                    s6 = peg$c3;
                   }
                 } else {
-                  result5 = null;
-                  pos = clone(pos1);
+                  peg$currPos = s6;
+                  s6 = peg$c3;
                 }
-                if (result5 !== null) {
-                  result4 = [];
-                  while (result5 !== null) {
-                    result4.push(result5);
-                    pos1 = clone(pos);
-                    pos2 = clone(pos);
-                    reportFailures++;
-                    result5 = parse_rd();
-                    reportFailures--;
-                    if (result5 === null) {
-                      result5 = "";
+              } else {
+                peg$currPos = s6;
+                s6 = peg$c3;
+              }
+              if (s6 !== peg$FAILED) {
+                while (s6 !== peg$FAILED) {
+                  s5.push(s6);
+                  s6 = peg$currPos;
+                  s7 = peg$currPos;
+                  peg$silentFails++;
+                  s8 = peg$parserd();
+                  peg$silentFails--;
+                  if (s8 === peg$FAILED) {
+                    s7 = peg$c6;
+                  } else {
+                    peg$currPos = s7;
+                    s7 = peg$c3;
+                  }
+                  if (s7 !== peg$FAILED) {
+                    s8 = peg$currPos;
+                    peg$silentFails++;
+                    s9 = peg$parseeol();
+                    peg$silentFails--;
+                    if (s9 === peg$FAILED) {
+                      s8 = peg$c6;
                     } else {
-                      result5 = null;
-                      pos = clone(pos2);
+                      peg$currPos = s8;
+                      s8 = peg$c3;
                     }
-                    if (result5 !== null) {
-                      pos2 = clone(pos);
-                      reportFailures++;
-                      result6 = parse_eol();
-                      reportFailures--;
-                      if (result6 === null) {
-                        result6 = "";
+                    if (s8 !== peg$FAILED) {
+                      if (input.length > peg$currPos) {
+                        s9 = input.charAt(peg$currPos);
+                        peg$currPos++;
                       } else {
-                        result6 = null;
-                        pos = clone(pos2);
+                        s9 = peg$FAILED;
+                        if (peg$silentFails === 0) { peg$fail(peg$c82); }
                       }
-                      if (result6 !== null) {
-                        if (input.length > pos.offset) {
-                          result7 = input.charAt(pos.offset);
-                          advance(pos, 1);
-                        } else {
-                          result7 = null;
-                          if (reportFailures === 0) {
-                            matchFailed("any character");
-                          }
-                        }
-                        if (result7 !== null) {
-                          result5 = [result5, result6, result7];
-                        } else {
-                          result5 = null;
-                          pos = clone(pos1);
-                        }
+                      if (s9 !== peg$FAILED) {
+                        s7 = [s7, s8, s9];
+                        s6 = s7;
                       } else {
-                        result5 = null;
-                        pos = clone(pos1);
+                        peg$currPos = s6;
+                        s6 = peg$c3;
                       }
                     } else {
-                      result5 = null;
-                      pos = clone(pos1);
+                      peg$currPos = s6;
+                      s6 = peg$c3;
                     }
+                  } else {
+                    peg$currPos = s6;
+                    s6 = peg$c3;
                   }
-                } else {
-                  result4 = null;
                 }
-                if (result4 !== null) {
-                  result5 = [];
-                  result6 = parse_ws();
-                  while (result6 !== null) {
-                    result5.push(result6);
-                    result6 = parse_ws();
-                  }
-                  if (result5 !== null) {
-                    result6 = parse_rd();
-                    if (result6 !== null) {
-                      result0 = [result0, result1, result2, result3, result4, result5, result6];
-                    } else {
-                      result0 = null;
-                      pos = clone(pos0);
-                    }
+              } else {
+                s5 = peg$c3;
+              }
+              if (s5 !== peg$FAILED) {
+                s6 = [];
+                s7 = peg$parsews();
+                while (s7 !== peg$FAILED) {
+                  s6.push(s7);
+                  s7 = peg$parsews();
+                }
+                if (s6 !== peg$FAILED) {
+                  s7 = peg$parserd();
+                  if (s7 !== peg$FAILED) {
+                    s1 = [s1, s2, s3, s4, s5, s6, s7];
+                    s0 = s1;
                   } else {
-                    result0 = null;
-                    pos = clone(pos0);
+                    peg$currPos = s0;
+                    s0 = peg$c3;
                   }
                 } else {
-                  result0 = null;
-                  pos = clone(pos0);
+                  peg$currPos = s0;
+                  s0 = peg$c3;
                 }
               } else {
-                result0 = null;
-                pos = clone(pos0);
+                peg$currPos = s0;
+                s0 = peg$c3;
               }
             } else {
-              result0 = null;
-              pos = clone(pos0);
+              peg$currPos = s0;
+              s0 = peg$c3;
             }
           } else {
-            result0 = null;
-            pos = clone(pos0);
+            peg$currPos = s0;
+            s0 = peg$c3;
           }
         } else {
-          result0 = null;
-          pos = clone(pos0);
+          peg$currPos = s0;
+          s0 = peg$c3;
         }
-        if (result0 === null) {
-          result0 = parse_reference();
-        }
-        return result0;
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c3;
       }
-      
-      function parse_ld() {
-        var result0;
-        
-        if (input.charCodeAt(pos.offset) === 123) {
-          result0 = "{";
-          advance(pos, 1);
-        } else {
-          result0 = null;
-          if (reportFailures === 0) {
-            matchFailed("\"{\"");
-          }
-        }
-        return result0;
+      if (s0 === peg$FAILED) {
+        s0 = peg$parsereference();
       }
-      
-      function parse_rd() {
-        var result0;
-        
-        if (input.charCodeAt(pos.offset) === 125) {
-          result0 = "}";
-          advance(pos, 1);
-        } else {
-          result0 = null;
-          if (reportFailures === 0) {
-            matchFailed("\"}\"");
-          }
-        }
-        return result0;
+
+      return s0;
+    }
+
+    function peg$parseld() {
+      var s0;
+
+      if (input.charCodeAt(peg$currPos) === 123) {
+        s0 = peg$c107;
+        peg$currPos++;
+      } else {
+        s0 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c108); }
       }
-      
-      function parse_lb() {
-        var result0;
-        
-        if (input.charCodeAt(pos.offset) === 91) {
-          result0 = "[";
-          advance(pos, 1);
-        } else {
-          result0 = null;
-          if (reportFailures === 0) {
-            matchFailed("\"[\"");
-          }
-        }
-        return result0;
+
+      return s0;
+    }
+
+    function peg$parserd() {
+      var s0;
+
+      if (input.charCodeAt(peg$currPos) === 125) {
+        s0 = peg$c109;
+        peg$currPos++;
+      } else {
+        s0 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c110); }
       }
-      
-      function parse_rb() {
-        var result0;
-        
-        if (input.charCodeAt(pos.offset) === 93) {
-          result0 = "]";
-          advance(pos, 1);
-        } else {
-          result0 = null;
-          if (reportFailures === 0) {
-            matchFailed("\"]\"");
-          }
-        }
-        return result0;
+
+      return s0;
+    }
+
+    function peg$parselb() {
+      var s0;
+
+      if (input.charCodeAt(peg$currPos) === 91) {
+        s0 = peg$c111;
+        peg$currPos++;
+      } else {
+        s0 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c112); }
+      }
+
+      return s0;
+    }
+
+    function peg$parserb() {
+      var s0;
+
+      if (input.charCodeAt(peg$currPos) === 93) {
+        s0 = peg$c113;
+        peg$currPos++;
+      } else {
+        s0 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c114); }
+      }
+
+      return s0;
+    }
+
+    function peg$parseeol() {
+      var s0;
+
+      if (input.charCodeAt(peg$currPos) === 10) {
+        s0 = peg$c115;
+        peg$currPos++;
+      } else {
+        s0 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c116); }
       }
-      
-      function parse_eol() {
-        var result0;
-        
-        if (input.charCodeAt(pos.offset) === 10) {
-          result0 = "\n";
-          advance(pos, 1);
+      if (s0 === peg$FAILED) {
+        if (input.substr(peg$currPos, 2) === peg$c117) {
+          s0 = peg$c117;
+          peg$currPos += 2;
         } else {
-          result0 = null;
-          if (reportFailures === 0) {
-            matchFailed("\"\\n\"");
-          }
+          s0 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c118); }
         }
-        if (result0 === null) {
-          if (input.substr(pos.offset, 2) === "\r\n") {
-            result0 = "\r\n";
-            advance(pos, 2);
+        if (s0 === peg$FAILED) {
+          if (input.charCodeAt(peg$currPos) === 13) {
+            s0 = peg$c119;
+            peg$currPos++;
           } else {
-            result0 = null;
-            if (reportFailures === 0) {
-              matchFailed("\"\\r\\n\"");
-            }
+            s0 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c120); }
           }
-          if (result0 === null) {
-            if (input.charCodeAt(pos.offset) === 13) {
-              result0 = "\r";
-              advance(pos, 1);
+          if (s0 === peg$FAILED) {
+            if (input.charCodeAt(peg$currPos) === 8232) {
+              s0 = peg$c121;
+              peg$currPos++;
             } else {
-              result0 = null;
-              if (reportFailures === 0) {
-                matchFailed("\"\\r\"");
-              }
+              s0 = peg$FAILED;
+              if (peg$silentFails === 0) { peg$fail(peg$c122); }
             }
-            if (result0 === null) {
-              if (input.charCodeAt(pos.offset) === 8232) {
-                result0 = "\u2028";
-                advance(pos, 1);
+            if (s0 === peg$FAILED) {
+              if (input.charCodeAt(peg$currPos) === 8233) {
+                s0 = peg$c123;
+                peg$currPos++;
               } else {
-                result0 = null;
-                if (reportFailures === 0) {
-                  matchFailed("\"\\u2028\"");
-                }
-              }
-              if (result0 === null) {
-                if (input.charCodeAt(pos.offset) === 8233) {
-                  result0 = "\u2029";
-                  advance(pos, 1);
-                } else {
-                  result0 = null;
-                  if (reportFailures === 0) {
-                    matchFailed("\"\\u2029\"");
-                  }
-                }
+                s0 = peg$FAILED;
+                if (peg$silentFails === 0) { peg$fail(peg$c124); }
               }
             }
           }
         }
-        return result0;
       }
-      
-      function parse_ws() {
-        var result0;
-        
-        if (/^[\t\x0B\f \xA0\uFEFF]/.test(input.charAt(pos.offset))) {
-          result0 = input.charAt(pos.offset);
-          advance(pos, 1);
-        } else {
-          result0 = null;
-          if (reportFailures === 0) {
-            matchFailed("[\\t\\x0B\\f \\xA0\\uFEFF]");
-          }
-        }
-        if (result0 === null) {
-          result0 = parse_eol();
-        }
-        return result0;
+
+      return s0;
+    }
+
+    function peg$parsews() {
+      var s0;
+
+      if (peg$c125.test(input.charAt(peg$currPos))) {
+        s0 = input.charAt(peg$currPos);
+        peg$currPos++;
+      } else {
+        s0 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c126); }
       }
-      
-      
-      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;
-      }
-      
-      
-      
-      var result = parseFunctions[startRule]();
-      
-      /*
-       * The parser is now in one of the following three states:
-       *
-       * 1. The parser successfully parsed the whole input.
-       *
-       *    - |result !== null|
-       *    - |pos.offset === input.length|
-       *    - |rightmostFailuresExpected| may or may not contain something
-       *
-       * 2. The parser successfully parsed only a part of the input.
-       *
-       *    - |result !== null|
-       *    - |pos.offset < input.length|
-       *    - |rightmostFailuresExpected| may or may not contain something
-       *
-       * 3. The parser did not successfully parse any part of the input.
-       *
-       *   - |result === null|
-       *   - |pos.offset === 0|
-       *   - |rightmostFailuresExpected| contains at least one failure
-       *
-       * All code following this comment (including called functions) must
-       * handle these states.
-       */
-      if (result === null || pos.offset !== input.length) {
-        var offset = Math.max(pos.offset, rightmostFailuresPos.offset);
-        var found = offset < input.length ? input.charAt(offset) : null;
-        var errorPosition = pos.offset > rightmostFailuresPos.offset ? pos : rightmostFailuresPos;
-        
-        throw new parser.SyntaxError(
-          cleanupExpected(rightmostFailuresExpected),
-          found,
-          offset,
-          errorPosition.line,
-          errorPosition.column
-        );
-      }
-      
-      return result;
-    },
-    
-    /* Returns the parser source code. */
-    toSource: function() { return this._source; }
-  };
-  
-  /* Thrown when a parser encounters a syntax error. */
-  
-  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.";
+      if (s0 === peg$FAILED) {
+        s0 = peg$parseeol();
+      }
+
+      return s0;
     }
-    
-    this.name = "SyntaxError";
-    this.expected = expected;
-    this.found = found;
-    this.message = buildMessage(expected, found);
-    this.offset = offset;
-    this.line = line;
-    this.column = column;
+
+    peg$result = peg$startRuleFunction();
+
+    if (peg$result !== peg$FAILED && peg$currPos === input.length) {
+      return peg$result;
+    } else {
+      if (peg$result !== peg$FAILED && peg$currPos < input.length) {
+        peg$fail({ type: "end", description: "end of input" });
+      }
+
+      throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos);
+    }
+  }
+
+  return {
+    SyntaxError: SyntaxError,
+    parse:       parse
   };
-  
-  result.SyntaxError.prototype = Error.prototype;
-  
-  return result;
 })();
 
   // expose parser methods
diff --git a/package.json b/package.json
index d0a07993..0b434dd2 100644
--- a/package.json
+++ b/package.json
@@ -47,7 +47,7 @@
     "views"
   ],
   "devDependencies": {
-    "pegjs": "0.7.0",
+    "pegjs": "0.8.0",
     "grunt": "~0.4.2",
     "grunt-contrib-connect": "~0.5.0",
     "grunt-template-jasmine-istanbul": "~0.2.5",
diff --git a/src/build.js b/src/build.js
index 97762a15..f8d8f73b 100644
--- a/src/build.js
+++ b/src/build.js
@@ -6,7 +6,8 @@ var peg  = require('pegjs'),
 
 var options = {
     cache: false,
-    trackLineAndColumn: true
+    trackLineAndColumn: true,
+    output: 'source'
 };
 
 var parser = peg.buildParser(fs.readFileSync(path.join(root, 'src', 'dust.pegjs'), 'utf8'), options),
@@ -16,4 +17,4 @@ var parser = peg.buildParser(fs.readFileSync(path.join(root, 'src', 'dust.pegjs'
     buildMessage = 'Do not edit the parser directly. This is a generated file created using a build script and the PEG grammar.';
 
 
-fs.writeFileSync(path.join(root, 'lib', 'parser.js'), umdWrapper.replace(parserPlaceholder, parser.toSource()).replace(buildMessagePlaceHolder, buildMessage).replace('this.SyntaxError','parser.SyntaxError'));
+fs.writeFileSync(path.join(root, 'lib', 'parser.js'), umdWrapper.replace(parserPlaceholder, parser).replace(buildMessagePlaceHolder, buildMessage).replace('this.SyntaxError','parser.SyntaxError'));
diff --git a/src/dust.pegjs b/src/dust.pegjs
index 65df1d4c..5b9a0667 100644
--- a/src/dust.pegjs
+++ b/src/dust.pegjs
@@ -5,7 +5,11 @@ start
    body is defined as anything that matches with the part 0 or more times
 ---------------------------------------------------------------------------------------------------------------------------------------*/
 body
-  = p:part* { return ["body"].concat(p).concat([['line', line], ['col', column]]) }
+  = p:part* {
+    return ["body"]
+           .concat(p)
+           .concat([['line', line()], ['col', column()]]);
+  }
 
 /*-------------------------------------------------------------------------------------------------------------------------------------
    part is defined as anything that matches with raw or comment or section or partial or special or reference or buffer
@@ -18,13 +22,24 @@ part
    plus bodies plus end_tag or sec_tag_start followed by a slash and closing brace
 ---------------------------------------------------------------------------------------------------------------------------------------*/
 section "section"
-  = t:sec_tag_start ws* rd b:body e:bodies n:end_tag? &{if( (!n) || (t[1].text !== n.text) ) { throw new Error("Expected end tag for "+t[1].text+" but it was not found. At line : "+line+", column : " + column)} return true;}
-    { e.push(["param", ["literal", "block"], b]); t.push(e); return t.concat([['line', line], ['col', column]]) }
-  / t:sec_tag_start ws* "/" rd
-  { t.push(["bodies"]); return t.concat([['line', line], ['col', column]]) }
+  = t:sec_tag_start ws* rd b:body e:bodies n:end_tag? &{
+    if( (!n) || (t[1].text !== n.text) ) {
+      error("Expected end tag for "+t[1].text+" but it was not found.");
+    }
+    return true;
+  }
+  {
+    e.push(["param", ["literal", "block"], b]);
+    t.push(e);
+    return t.concat([['line', line()], ['col', column()]]);
+  }
+  / t:sec_tag_start ws* "/" rd {
+    t.push(["bodies"]);
+    return t.concat([['line', line()], ['col', column()]]);
+  }
 
 /*-------------------------------------------------------------------------------------------------------------------------------------
-   sec_tag_start is defined as matching an opening brace followed by one of #?^<+@% plus identifier plus context plus param 
+   sec_tag_start is defined as matching an opening brace followed by one of #?^<+@% plus identifier plus context plus param
    followed by 0 or more white spaces
 ---------------------------------------------------------------------------------------------------------------------------------------*/
 sec_tag_start
@@ -32,7 +47,7 @@ sec_tag_start
   { return [t, n, c, p] }
 
 /*-------------------------------------------------------------------------------------------------------------------------------------
-   end_tag is defined as matching an opening brace followed by a slash plus 0 or more white spaces plus identifier followed 
+   end_tag is defined as matching an opening brace followed by a slash plus 0 or more white spaces plus identifier followed
    by 0 or more white spaces and ends with closing brace
 ---------------------------------------------------------------------------------------------------------------------------------------*/
 end_tag "end tag"
@@ -65,15 +80,18 @@ bodies "bodies"
 ---------------------------------------------------------------------------------------------------------------------------------------*/
 reference "reference"
   = ld n:identifier f:filters rd
-  { return ["reference", n, f].concat([['line', line], ['col', column]]) }
+  { return ["reference", n, f].concat([['line', line()], ['col', column()]]) }
 
 /*-------------------------------------------------------------------------------------------------------------------------------------
-  partial is defined as matching a opening brace followed by a > plus anything that matches with key or inline plus 
+  partial is defined as matching a opening brace followed by a > plus anything that matches with key or inline plus
   context followed by slash and closing brace
 ---------------------------------------------------------------------------------------------------------------------------------------*/
 partial "partial"
   = ld s:(">"/"+") ws* n:(k:key {return ["literal", k]} / inline) c:context p:params ws* "/" rd
-  { var key = (s ===">")? "partial" : s; return [key, n, c, p].concat([['line', line], ['col', column]]) }
+  {
+    var key = (s === ">") ? "partial" : s;
+    return [key, n, c, p].concat([['line', line()], ['col', column()]]);
+  }
 
 /*-------------------------------------------------------------------------------------------------------------------------------------
    filters is defined as matching a pipe character followed by anything that matches the key
@@ -87,7 +105,7 @@ filters "filters"
 ---------------------------------------------------------------------------------------------------------------------------------------*/
 special "special"
   = ld "~" k:key rd
-  { return ["special", k].concat([['line', line], ['col', column]]) }
+  { return ["special", k].concat([['line', line()], ['col', column()]]) }
 
 /*-------------------------------------------------------------------------------------------------------------------------------------
    identifier is defined as matching a path or key
@@ -106,26 +124,26 @@ integer "integer"
   = digits:[0-9]+ { return parseInt(digits.join(""), 10); }
 
 /*-------------------------------------------------------------------------------------------------------------------------------------
-  path is defined as matching a key plus one or more characters of key preceded by a dot 
+  path is defined as matching a key plus one or more characters of key preceded by a dot
 ---------------------------------------------------------------------------------------------------------------------------------------*/
 path "path"
   = k:key? d:(array_part / array)+ {
     d = d[0];
     if (k && d) {
       d.unshift(k);
-      return [false, d].concat([['line', line], ['col', column]]);
+      return [false, d].concat([['line', line()], ['col', column()]]);
     }
-    return [true, d].concat([['line', line], ['col', column]]);
+    return [true, d].concat([['line', line()], ['col', column()]]);
   }
   / "." d:(array_part / array)* {
     if (d.length > 0) {
-      return [true, d[0]].concat([['line', line], ['col', column]]);
+      return [true, d[0]].concat([['line', line()], ['col', column()]]);
     }
-    return [true, []].concat([['line', line], ['col', column]]);
+    return [true, []].concat([['line', line()], ['col', column()]]);
   }
 
 /*-------------------------------------------------------------------------------------------------------------------------------------
-   key is defined as a character matching a to z, upper or lower case, followed by 0 or more alphanumeric characters  
+   key is defined as a character matching a to z, upper or lower case, followed by 0 or more alphanumeric characters
 ---------------------------------------------------------------------------------------------------------------------------------------*/
 key "key"
   = h:[a-zA-Z_$] t:[0-9a-zA-Z_$-]*
@@ -138,25 +156,25 @@ array_part "array_part"
   = d:("." k:key {return k})+ a:(array)? { if (a) { return d.concat(a); } else { return d; } }
 
 /*-------------------------------------------------------------------------------------------------------------------------------------
-   inline params is defined as matching two double quotes or double quotes plus literal followed by closing double quotes or  
+   inline params is defined as matching two double quotes or double quotes plus literal followed by closing double quotes or
    double quotes plus inline_part followed by the closing double quotes
 ---------------------------------------------------------------------------------------------------------------------------------------*/
 inline "inline"
-  = '"' '"'                 { return ["literal", ""].concat([['line', line], ['col', column]]) }
-  / '"' l:literal '"'       { return ["literal", l].concat([['line', line], ['col', column]]) }
-  / '"' p:inline_part+ '"'  { return ["body"].concat(p).concat([['line', line], ['col', column]]) }
+  = '"' '"'                 { return ["literal", ""].concat([['line', line()], ['col', column()]]) }
+  / '"' l:literal '"'       { return ["literal", l].concat([['line', line()], ['col', column()]]) }
+  / '"' p:inline_part+ '"'  { return ["body"].concat(p).concat([['line', line()], ['col', column()]]) }
 
 /*-------------------------------------------------------------------------------------------------------------------------------------
-  inline_part is defined as matching a special or reference or literal  
+  inline_part is defined as matching a special or reference or literal
 ---------------------------------------------------------------------------------------------------------------------------------------*/
 inline_part
   = special / reference / l:literal { return ["buffer", l] }
 
 buffer "buffer"
   = e:eol w:ws*
-  { return ["format", e, w.join('')].concat([['line', line], ['col', column]]) }
+  { return ["format", e, w.join('')].concat([['line', line()], ['col', column()]]) }
   / b:(!tag !raw !comment !eol c:. {return c})+
-  { return ["buffer", b.join('')].concat([['line', line], ['col', column]]) }
+  { return ["buffer", b.join('')].concat([['line', line()], ['col', column()]]) }
 
 /*-------------------------------------------------------------------------------------------------------------------------------------
    literal is defined as matching esc or any character except the double quotes and it cannot be a tag
@@ -170,13 +188,13 @@ esc
 
 raw "raw"
   = "{`" rawText:(!"`}" char:. {return char})* "`}"
-  { return ["raw", rawText.join('')].concat([['line', line], ['col', column]]) }
+  { return ["raw", rawText.join('')].concat([['line', line()], ['col', column()]]) }
 comment "comment"
   = "{!" c:(!"!}" c:. {return c})* "!}"
-  { return ["comment", c.join('')].concat([['line', line], ['col', column]]) }
+  { return ["comment", c.join('')].concat([['line', line()], ['col', column()]]) }
 
 /*-------------------------------------------------------------------------------------------------------------------------------------
-   tag is defined as matching an opening brace plus any of #?^><+%:@/~% plus 0 or more whitespaces plus any character or characters that 
+   tag is defined as matching an opening brace plus any of #?^><+%:@/~% plus 0 or more whitespaces plus any character or characters that
    doesn't match rd or eol plus 0 or more whitespaces plus a closing brace
 ---------------------------------------------------------------------------------------------------------------------------------------*/
 tag
@@ -195,7 +213,7 @@ lb
 rb
   = "]"
 
-eol 
+eol
   = "\n"        //line feed
   / "\r\n"      //carriage + line feed
   / "\r"        //carriage return
diff --git a/test/jasmine-test/spec/coreTests.js b/test/jasmine-test/spec/coreTests.js
index ec4b2479..5cbe2b23 100755
--- a/test/jasmine-test/spec/coreTests.js
+++ b/test/jasmine-test/spec/coreTests.js
@@ -968,7 +968,7 @@ var coreTests = [
 /**
  * PARTIAL DEFINITIONS TESTS
  */
-  { 
+  {
     name: "partial definitions",
     tests: [
       {
@@ -1399,7 +1399,7 @@ var coreTests = [
         name:     "error: whitespaces between the opening brace and any of (#,?,@,^,+,%) is not allowed",
         source:   '{ # helper foo="bar" boo="boo" } {/helper}',
         context:  { "helper": function(chunk, context, bodies, params) { return chunk.write(params.boo + " " + params.foo); } },
-        error: 'Expected buffer, comment, partial, raw, reference, section or special but "{" found. At line : 1, column : 1',
+        error: 'Expected buffer, comment, end of input, partial, raw, reference, section or special but "{" found. At line : 1, column : 1',
         message: "should show an error for whitespces between the opening brace and any of (#,?,@,^,+,%)"
       },
       {
@@ -1427,7 +1427,7 @@ var coreTests = [
         name:     "error: whitespaces between the forward slash and the closing brace in self closing tags",
         source:   '{#helper foo="bar" boo="boo" / }',
         context:  { "helper": function(chunk, context, bodies, params) { return chunk.write(params.boo + " " + params.foo); } },
-        error: 'Expected buffer, comment, partial, raw, reference, section or special but "{" found. At line : 1, column : 1',
+        error: 'Expected buffer, comment, end of input, partial, raw, reference, section or special but "{" found. At line : 1, column : 1',
         message: "should show an error for whitespaces  etween the forward slash and the closing brace in self closing tags"
       },
       {
@@ -1441,7 +1441,7 @@ var coreTests = [
         name: "error : whitespaces between the '{' plus '>' and partial identifier is not supported",
         source: '{ > partial/} {> "hello_world"/} {> "{ref}"/}',
         context: { "name": "Jim", "count": 42, "ref": "hello_world" },
-        error: 'Expected buffer, comment, partial, raw, reference, section or special but "{" found. At line : 1, column : 1',
+        error: 'Expected buffer, comment, end of input, partial, raw, reference, section or special but "{" found. At line : 1, column : 1',
         message: "should show an error for whitespaces between the '{' plus '>' and partial identifier"
       },
       {
@@ -1541,7 +1541,7 @@ var coreTests = [
         name: "Dust syntax error",
         source: "RRR {##}",
         context: { name: "Mick", count: 30 },
-        error: 'Expected buffer, comment, partial, raw, reference, section or special but "{" found. At line : 1, column : 5',
+        error: 'Expected buffer, comment, end of input, partial, raw, reference, section or special but "{" found. At line : 1, column : 5',
         message: "should test that the error message shows line and column."
       },
       {