Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reduce generated code size, a lot #8

Open
rjrodger opened this issue Dec 22, 2015 · 3 comments
Open

reduce generated code size, a lot #8

rjrodger opened this issue Dec 22, 2015 · 3 comments

Comments

@rjrodger
Copy link
Collaborator

open problem... any ideas?

@AdrieanKhisbe
Copy link
Contributor

Maybe have a look to https://github.com/mishoo/UglifyJS2,
rewrite of uglify. Don't know if it improves compression.

@rjrodger
Copy link
Collaborator Author

@AdrieanKhisbe it's not so much code volume, as complexity. Needs optimization of the parser generated code.

@ilyazub
Copy link

ilyazub commented Mar 8, 2021

PEG.js can generate a size-optimized parser but I haven't compared the performance. The regenerated parser from the grammar is 748 LOC.

@rjrodger Why do you want to reduce the size of parser-generated code?

Size-optimized parser
module.exports = /*
 * Generated by PEG.js 0.10.0.
 *
 * http://pegjs.org/
 */
(function() {
  "use strict";

  function peg$subclass(child, parent) {
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor();
  }

  function peg$SyntaxError(message, expected, found, location) {
    this.message  = message;
    this.expected = expected;
    this.found    = found;
    this.location = location;
    this.name     = "SyntaxError";

    if (typeof Error.captureStackTrace === "function") {
      Error.captureStackTrace(this, peg$SyntaxError);
    }
  }

  peg$subclass(peg$SyntaxError, Error);

  peg$SyntaxError.buildMessage = function(expected, found) {
    var DESCRIBE_EXPECTATION_FNS = {
          literal: function(expectation) {
            return "\"" + literalEscape(expectation.text) + "\"";
          },

          "class": function(expectation) {
            var escapedParts = "",
                i;

            for (i = 0; i < expectation.parts.length; i++) {
              escapedParts += expectation.parts[i] instanceof Array
                ? classEscape(expectation.parts[i][0]) + "-" + classEscape(expectation.parts[i][1])
                : classEscape(expectation.parts[i]);
            }

            return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]";
          },

          any: function(expectation) {
            return "any character";
          },

          end: function(expectation) {
            return "end of input";
          },

          other: function(expectation) {
            return expectation.description;
          }
        };

    function hex(ch) {
      return ch.charCodeAt(0).toString(16).toUpperCase();
    }

    function literalEscape(s) {
      return s
        .replace(/\\/g, '\\\\')
        .replace(/"/g,  '\\"')
        .replace(/\0/g, '\\0')
        .replace(/\t/g, '\\t')
        .replace(/\n/g, '\\n')
        .replace(/\r/g, '\\r')
        .replace(/[\x00-\x0F]/g,          function(ch) { return '\\x0' + hex(ch); })
        .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x'  + hex(ch); });
    }

    function classEscape(s) {
      return s
        .replace(/\\/g, '\\\\')
        .replace(/\]/g, '\\]')
        .replace(/\^/g, '\\^')
        .replace(/-/g,  '\\-')
        .replace(/\0/g, '\\0')
        .replace(/\t/g, '\\t')
        .replace(/\n/g, '\\n')
        .replace(/\r/g, '\\r')
        .replace(/[\x00-\x0F]/g,          function(ch) { return '\\x0' + hex(ch); })
        .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x'  + hex(ch); });
    }

    function describeExpectation(expectation) {
      return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);
    }

    function describeExpected(expected) {
      var descriptions = new Array(expected.length),
          i, j;

      for (i = 0; i < expected.length; i++) {
        descriptions[i] = describeExpectation(expected[i]);
      }

      descriptions.sort();

      if (descriptions.length > 0) {
        for (i = 1, j = 1; i < descriptions.length; i++) {
          if (descriptions[i - 1] !== descriptions[i]) {
            descriptions[j] = descriptions[i];
            j++;
          }
        }
        descriptions.length = j;
      }

      switch (descriptions.length) {
        case 1:
          return descriptions[0];

        case 2:
          return descriptions[0] + " or " + descriptions[1];

        default:
          return descriptions.slice(0, -1).join(", ")
            + ", or "
            + descriptions[descriptions.length - 1];
      }
    }

    function describeFound(found) {
      return found ? "\"" + literalEscape(found) + "\"" : "end of input";
    }

    return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found.";
  };

  function peg$parse(input, options) {
    options = options !== void 0 ? options : {};

    var peg$FAILED = {},

        peg$startRuleIndices = { start: 0 },
        peg$startRuleIndex   = 0,

        peg$consts = [
          function(object) { return object; },
          function(array) { return array; },
          "{",
          peg$literalExpectation("{", false),
          "}",
          peg$literalExpectation("}", false),
          function() { return {};      },
          function(members) { return members; },
          ",",
          peg$literalExpectation(",", false),
          function(head, tail) {
                var result = {};
                if( head ) { result[head[0]] = fixNull(head[1]); }
                for (var i = 0; i < tail.length; i++) {
                  result[tail[i][2][0]] = fixNull(tail[i][2][1]);
                }
                return result;
              },
          ":",
          peg$literalExpectation(":", false),
          function(name, value) { return [name, value]; },
          "[",
          peg$literalExpectation("[", false),
          "]",
          peg$literalExpectation("]", false),
          function() { return [];       },
          function(elements) { return elements; },
          function(head, tail) {
                var result = [];
                if( typeof head !== 'undefined' && head !== null ) { result.push( fixNull(head) ) }
                for (var i = 0; i < tail.length; i++) {
                  result.push(fixNull(tail[i][2]));
                }
                return result;
              },
          "true",
          peg$literalExpectation("true", false),
          function() { return true;  },
          "false",
          peg$literalExpectation("false", false),
          function() { return false; },
          "null",
          peg$literalExpectation("null", false),
          function() { return null_; },
          function(lit) { return lit.join('').trim() },
          peg$otherExpectation("double-quote string"),
          "\"",
          peg$literalExpectation("\"", false),
          function() { return "";    },
          function(chars) { return chars; },
          peg$otherExpectation("single-quote string"),
          "'",
          peg$literalExpectation("'", false),
          function(chars) { return chars.join(""); },
          /^[^"\\\0-\x1F\x7F]/,
          peg$classExpectation(["\"", "\\", ["\0", "\x1F"], "\x7F"], true, false),
          "\\\"",
          peg$literalExpectation("\\\"", false),
          function() { return '"';  },
          "\\\\",
          peg$literalExpectation("\\\\", false),
          function() { return "\\"; },
          "\\/",
          peg$literalExpectation("\\/", false),
          function() { return "/";  },
          "\\b",
          peg$literalExpectation("\\b", false),
          function() { return "\b"; },
          "\\f",
          peg$literalExpectation("\\f", false),
          function() { return "\f"; },
          "\\n",
          peg$literalExpectation("\\n", false),
          function() { return "\n"; },
          "\\r",
          peg$literalExpectation("\\r", false),
          function() { return "\r"; },
          "\\t",
          peg$literalExpectation("\\t", false),
          function() { return "\t"; },
          "\\u",
          peg$literalExpectation("\\u", false),
          function(h1, h2, h3, h4) {
                return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4)); },
          /^[^'\\\0-\x1F\x7F]/,
          peg$classExpectation(["'", "\\", ["\0", "\x1F"], "\x7F"], true, false),
          "\\'",
          peg$literalExpectation("\\'", false),
          function() { return '\'';  },
          peg$otherExpectation("key"),
          /^[a-zA-Z0-9_$\-]/,
          peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"], "_", "$", "-"], false, false),
          function(chars) { return chars.join('') },
          /^[^,}\]]/,
          peg$classExpectation([",", "}", "]"], true, false),
          peg$otherExpectation("number"),
          function(int_, frac, exp, suffix) { return 0 === suffix.length ? parseFloat(int_ + frac + exp) : (int_  + frac + exp + suffix.join('')).trim(); },
          function(int_, frac, suffix) { return 0 === suffix.length ? parseFloat(int_ + frac) : (int_ + frac + suffix.join('')).trim(); },
          function(int_, exp, suffix) { return 0 === suffix.length ? parseFloat(int_ + exp) : (int_ + exp + suffix.join('')).trim(); },
          function(int_, suffix) { return 0 === suffix.length ? parseFloat(int_) : (int_ + suffix.join('')).trim(); },
          function(digit19, digits) { return digit19 + digits;       },
          "-",
          peg$literalExpectation("-", false),
          function(digit19, digits) { return "-" + digit19 + digits; },
          function(digit) { return "-" + digit;            },
          ".",
          peg$literalExpectation(".", false),
          function(digits) { return "." + digits; },
          function(e, digits) { return e + digits; },
          function(digits) { return digits.join(""); },
          /^[eE]/,
          peg$classExpectation(["e", "E"], false, false),
          /^[+\-]/,
          peg$classExpectation(["+", "-"], false, false),
          function(e, sign) { return e + (sign?sign:''); },
          /^[0-9]/,
          peg$classExpectation([["0", "9"]], false, false),
          /^[1-9]/,
          peg$classExpectation([["1", "9"]], false, false),
          /^[0-9a-fA-F]/,
          peg$classExpectation([["0", "9"], ["a", "f"], ["A", "F"]], false, false),
          peg$otherExpectation("whitespace"),
          /^[ \t\n\r]/,
          peg$classExpectation([" ", "\t", "\n", "\r"], false, false)
        ],

        peg$bytecode = [
          peg$decode("%;9/1#;!/($8\": \"! )(\"'#&'#.; &%;9/1#;$/($8\":!\"! )(\"'#&'#"),
          peg$decode("%2\"\"\"6\"7#/H#;9/?$2$\"\"6$7%/0$;9/'$8$:&$ )($'#(#'#(\"'#&'#.b &%2\"\"\"6\"7#/R#;9/I$;\"/@$2$\"\"6$7%/1$;9/($8%:'%!\")(%'#($'#(#'#(\"'#&'#"),
          peg$decode("%2(\"\"6(7).\" &\"/\xA8#;#.\" &\"/\x9A$$%2(\"\"6(7)/5#;9/,$;#/#$+#)(#'#(\"'#&'#0E*%2(\"\"6(7)/5#;9/,$;#/#$+#)(#'#(\"'#&'#&/F$2(\"\"6(7).\" &\"/2$;9/)$8%:*%\"#\")(%'#($'#(#'#(\"'#&'#"),
          peg$decode("%;-/S#;9/J$2+\"\"6+7,/;$;9/2$;&/)$8%:-%\"$ )(%'#($'#(#'#(\"'#&'#"),
          peg$decode("%2.\"\"6.7//H#;9/?$20\"\"6071/0$;9/'$8$:2$ )($'#(#'#(\"'#&'#.b &%2.\"\"6.7//R#;9/I$;%/@$20\"\"6071/1$;9/($8%:3%!\")(%'#($'#(#'#(\"'#&'#"),
          peg$decode("%2(\"\"6(7).\" &\"/\xA8#;&.\" &\"/\x9A$$%2(\"\"6(7)/5#;9/,$;&/#$+#)(#'#(\"'#&'#0E*%2(\"\"6(7)/5#;9/,$;&/#$+#)(#'#(\"'#&'#&/F$2(\"\"6(7).\" &\"/2$;9/)$8%:4%\"#\")(%'#($'#(#'#(\"'#&'#"),
          peg$decode(";'.\xB0 &;(.\xAA &;!.\xA4 &;$.\x9E &%25\"\"6576/0#;9/'$8\":7\" )(\"'#&'#.{ &%28\"\"6879/0#;9/'$8\"::\" )(\"'#&'#.X &%2;\"\"6;7</0#;9/'$8\":=\" )(\"'#&'#.5 &;0./ &%;./' 8!:>!! )"),
          peg$decode("<%2@\"\"6@7A/?#2@\"\"6@7A/0$;9/'$8#:B# )(#'#(\"'#&'#.Y &%2@\"\"6@7A/I#;)/@$2@\"\"6@7A/1$;9/($8$:C$!\")($'#(#'#(\"'#&'#=.\" 7?"),
          peg$decode("<%2E\"\"6E7F/?#2E\"\"6E7F/0$;9/'$8#:B# )(#'#(\"'#&'#.Y &%2E\"\"6E7F/I#;+/@$2E\"\"6E7F/1$;9/($8$:C$!\")($'#(#'#(\"'#&'#=.\" 7D"),
          peg$decode("%$;*/&#0#*;*&&&#/' 8!:G!! )"),
          peg$decode("4H\"\"5!7I.\u0117 &%2J\"\"6J7K/& 8!:L! ).\u0100 &%2M\"\"6M7N/& 8!:O! ).\xE9 &%2P\"\"6P7Q/& 8!:R! ).\xD2 &%2S\"\"6S7T/& 8!:U! ).\xBB &%2V\"\"6V7W/& 8!:X! ).\xA4 &%2Y\"\"6Y7Z/& 8!:[! ).\x8D &%2\\\"\"6\\7]/& 8!:^! ).v &%2_\"\"6_7`/& 8!:a! )._ &%2b\"\"6b7c/O#;8/F$;8/=$;8/4$;8/+$8%:d%$#\"! )(%'#($'#(#'#(\"'#&'#"),
          peg$decode("%$;,/&#0#*;,&&&#/' 8!:G!! )"),
          peg$decode("4e\"\"5!7f.\u0117 &%2g\"\"6g7h/& 8!:i! ).\u0100 &%2M\"\"6M7N/& 8!:O! ).\xE9 &%2P\"\"6P7Q/& 8!:R! ).\xD2 &%2S\"\"6S7T/& 8!:U! ).\xBB &%2V\"\"6V7W/& 8!:X! ).\xA4 &%2Y\"\"6Y7Z/& 8!:[! ).\x8D &%2\\\"\"6\\7]/& 8!:^! ).v &%2_\"\"6_7`/& 8!:a! )._ &%2b\"\"6b7c/O#;8/F$;8/=$;8/4$;8/+$8%:d%$#\"! )(%'#($'#(#'#(\"'#&'#"),
          peg$decode("<;'.N &;(.H &%$4k\"\"5!7l/,#0)*4k\"\"5!7l&&&#/' 8!:m!! )=.\" 7j"),
          peg$decode("$;//&#0#*;/&&&#"),
          peg$decode("4n\"\"5!7o"),
          peg$decode("<%;1/V#;2/M$;3/D$;9/;$$;/0#*;/&/+$8%:q%$$#\" )(%'#($'#(#'#(\"'#&'#.\xBE &%;1/L#;2/C$;9/:$$;/0#*;/&/*$8$:r$##\" )($'#(#'#(\"'#&'#.\x85 &%;1/L#;3/C$;9/:$$;/0#*;/&/*$8$:s$##\" )($'#(#'#(\"'#&'#.L &%;1/B#;9/9$$;/0#*;/&/)$8#:t#\"\" )(#'#(\"'#&'#=.\" 7p"),
          peg$decode("%;7/2#;4/)$8\":u\"\"! )(\"'#&'#.u &;6.o &%2v\"\"6v7w/;#;7/2$;4/)$8#:x#\"! )(#'#(\"'#&'#.A &%2v\"\"6v7w/1#;6/($8\":y\"! )(\"'#&'#"),
          peg$decode("%2z\"\"6z7{/1#;4/($8\":|\"! )(\"'#&'#"),
          peg$decode("%;5/2#;4/)$8\":}\"\"! )(\"'#&'#"),
          peg$decode("%$;6/&#0#*;6&&&#/' 8!:~!! )"),
          peg$decode("%4\x7F\"\"5!7\x80/=#4\x81\"\"5!7\x82.\" &\"/)$8\":\x83\"\"! )(\"'#&'#"),
          peg$decode("4\x84\"\"5!7\x85"),
          peg$decode("4\x86\"\"5!7\x87"),
          peg$decode("4\x88\"\"5!7\x89"),
          peg$decode("<$;:0#*;:&=.\" 7\x8A"),
          peg$decode("4\x8B\"\"5!7\x8C")
        ],

        peg$currPos          = 0,
        peg$savedPos         = 0,
        peg$posDetailsCache  = [{ line: 1, column: 1 }],
        peg$maxFailPos       = 0,
        peg$maxFailExpected  = [],
        peg$silentFails      = 0,

        peg$result;

    if ("startRule" in options) {
      if (!(options.startRule in peg$startRuleIndices)) {
        throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
      }

      peg$startRuleIndex = peg$startRuleIndices[options.startRule];
    }

    function text() {
      return input.substring(peg$savedPos, peg$currPos);
    }

    function location() {
      return peg$computeLocation(peg$savedPos, peg$currPos);
    }

    function expected(description, location) {
      location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)

      throw peg$buildStructuredError(
        [peg$otherExpectation(description)],
        input.substring(peg$savedPos, peg$currPos),
        location
      );
    }

    function error(message, location) {
      location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)

      throw peg$buildSimpleError(message, location);
    }

    function peg$literalExpectation(text, ignoreCase) {
      return { type: "literal", text: text, ignoreCase: ignoreCase };
    }

    function peg$classExpectation(parts, inverted, ignoreCase) {
      return { type: "class", parts: parts, inverted: inverted, ignoreCase: ignoreCase };
    }

    function peg$anyExpectation() {
      return { type: "any" };
    }

    function peg$endExpectation() {
      return { type: "end" };
    }

    function peg$otherExpectation(description) {
      return { type: "other", description: description };
    }

    function peg$computePosDetails(pos) {
      var details = peg$posDetailsCache[pos], p;

      if (details) {
        return details;
      } else {
        p = pos - 1;
        while (!peg$posDetailsCache[p]) {
          p--;
        }

        details = peg$posDetailsCache[p];
        details = {
          line:   details.line,
          column: details.column
        };

        while (p < pos) {
          if (input.charCodeAt(p) === 10) {
            details.line++;
            details.column = 1;
          } else {
            details.column++;
          }

          p++;
        }

        peg$posDetailsCache[pos] = details;
        return details;
      }
    }

    function peg$computeLocation(startPos, endPos) {
      var startPosDetails = peg$computePosDetails(startPos),
          endPosDetails   = peg$computePosDetails(endPos);

      return {
        start: {
          offset: startPos,
          line:   startPosDetails.line,
          column: startPosDetails.column
        },
        end: {
          offset: endPos,
          line:   endPosDetails.line,
          column: endPosDetails.column
        }
      };
    }

    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$buildSimpleError(message, location) {
      return new peg$SyntaxError(message, null, null, location);
    }

    function peg$buildStructuredError(expected, found, location) {
      return new peg$SyntaxError(
        peg$SyntaxError.buildMessage(expected, found),
        expected,
        found,
        location
      );
    }

    function peg$decode(s) {
      var bc = new Array(s.length), i;

      for (i = 0; i < s.length; i++) {
        bc[i] = s.charCodeAt(i) - 32;
      }

      return bc;
    }

    function peg$parseRule(index) {
      var bc    = peg$bytecode[index],
          ip    = 0,
          ips   = [],
          end   = bc.length,
          ends  = [],
          stack = [],
          params, i;

      while (true) {
        while (ip < end) {
          switch (bc[ip]) {
            case 0:
              stack.push(peg$consts[bc[ip + 1]]);
              ip += 2;
              break;

            case 1:
              stack.push(void 0);
              ip++;
              break;

            case 2:
              stack.push(null);
              ip++;
              break;

            case 3:
              stack.push(peg$FAILED);
              ip++;
              break;

            case 4:
              stack.push([]);
              ip++;
              break;

            case 5:
              stack.push(peg$currPos);
              ip++;
              break;

            case 6:
              stack.pop();
              ip++;
              break;

            case 7:
              peg$currPos = stack.pop();
              ip++;
              break;

            case 8:
              stack.length -= bc[ip + 1];
              ip += 2;
              break;

            case 9:
              stack.splice(-2, 1);
              ip++;
              break;

            case 10:
              stack[stack.length - 2].push(stack.pop());
              ip++;
              break;

            case 11:
              stack.push(stack.splice(stack.length - bc[ip + 1], bc[ip + 1]));
              ip += 2;
              break;

            case 12:
              stack.push(input.substring(stack.pop(), peg$currPos));
              ip++;
              break;

            case 13:
              ends.push(end);
              ips.push(ip + 3 + bc[ip + 1] + bc[ip + 2]);

              if (stack[stack.length - 1]) {
                end = ip + 3 + bc[ip + 1];
                ip += 3;
              } else {
                end = ip + 3 + bc[ip + 1] + bc[ip + 2];
                ip += 3 + bc[ip + 1];
              }

              break;

            case 14:
              ends.push(end);
              ips.push(ip + 3 + bc[ip + 1] + bc[ip + 2]);

              if (stack[stack.length - 1] === peg$FAILED) {
                end = ip + 3 + bc[ip + 1];
                ip += 3;
              } else {
                end = ip + 3 + bc[ip + 1] + bc[ip + 2];
                ip += 3 + bc[ip + 1];
              }

              break;

            case 15:
              ends.push(end);
              ips.push(ip + 3 + bc[ip + 1] + bc[ip + 2]);

              if (stack[stack.length - 1] !== peg$FAILED) {
                end = ip + 3 + bc[ip + 1];
                ip += 3;
              } else {
                end = ip + 3 + bc[ip + 1] + bc[ip + 2];
                ip += 3 + bc[ip + 1];
              }

              break;

            case 16:
              if (stack[stack.length - 1] !== peg$FAILED) {
                ends.push(end);
                ips.push(ip);

                end = ip + 2 + bc[ip + 1];
                ip += 2;
              } else {
                ip += 2 + bc[ip + 1];
              }

              break;

            case 17:
              ends.push(end);
              ips.push(ip + 3 + bc[ip + 1] + bc[ip + 2]);

              if (input.length > peg$currPos) {
                end = ip + 3 + bc[ip + 1];
                ip += 3;
              } else {
                end = ip + 3 + bc[ip + 1] + bc[ip + 2];
                ip += 3 + bc[ip + 1];
              }

              break;

            case 18:
              ends.push(end);
              ips.push(ip + 4 + bc[ip + 2] + bc[ip + 3]);

              if (input.substr(peg$currPos, peg$consts[bc[ip + 1]].length) === peg$consts[bc[ip + 1]]) {
                end = ip + 4 + bc[ip + 2];
                ip += 4;
              } else {
                end = ip + 4 + bc[ip + 2] + bc[ip + 3];
                ip += 4 + bc[ip + 2];
              }

              break;

            case 19:
              ends.push(end);
              ips.push(ip + 4 + bc[ip + 2] + bc[ip + 3]);

              if (input.substr(peg$currPos, peg$consts[bc[ip + 1]].length).toLowerCase() === peg$consts[bc[ip + 1]]) {
                end = ip + 4 + bc[ip + 2];
                ip += 4;
              } else {
                end = ip + 4 + bc[ip + 2] + bc[ip + 3];
                ip += 4 + bc[ip + 2];
              }

              break;

            case 20:
              ends.push(end);
              ips.push(ip + 4 + bc[ip + 2] + bc[ip + 3]);

              if (peg$consts[bc[ip + 1]].test(input.charAt(peg$currPos))) {
                end = ip + 4 + bc[ip + 2];
                ip += 4;
              } else {
                end = ip + 4 + bc[ip + 2] + bc[ip + 3];
                ip += 4 + bc[ip + 2];
              }

              break;

            case 21:
              stack.push(input.substr(peg$currPos, bc[ip + 1]));
              peg$currPos += bc[ip + 1];
              ip += 2;
              break;

            case 22:
              stack.push(peg$consts[bc[ip + 1]]);
              peg$currPos += peg$consts[bc[ip + 1]].length;
              ip += 2;
              break;

            case 23:
              stack.push(peg$FAILED);
              if (peg$silentFails === 0) {
                peg$fail(peg$consts[bc[ip + 1]]);
              }
              ip += 2;
              break;

            case 24:
              peg$savedPos = stack[stack.length - 1 - bc[ip + 1]];
              ip += 2;
              break;

            case 25:
              peg$savedPos = peg$currPos;
              ip++;
              break;

            case 26:
              params = bc.slice(ip + 4, ip + 4 + bc[ip + 3]);
              for (i = 0; i < bc[ip + 3]; i++) {
                params[i] = stack[stack.length - 1 - params[i]];
              }

              stack.splice(
                stack.length - bc[ip + 2],
                bc[ip + 2],
                peg$consts[bc[ip + 1]].apply(null, params)
              );

              ip += 4 + bc[ip + 3];
              break;

            case 27:
              stack.push(peg$parseRule(bc[ip + 1]));
              ip += 2;
              break;

            case 28:
              peg$silentFails++;
              ip++;
              break;

            case 29:
              peg$silentFails--;
              ip++;
              break;

            default:
              throw new Error("Invalid opcode: " + bc[ip] + ".");
          }
        }

        if (ends.length > 0) {
          end = ends.pop();
          ip = ips.pop();
        } else {
          break;
        }
      }

      return stack[0];
    }


      /*
       * We can't return |null| in the |value| rule because that would mean parse
       * failure. So we return a special object instead and convert it to |null|
       * later.
       */

      var null_ = new Object;

      function fixNull(value) {
        return value === null_ ? null : value;
      }


    peg$result = peg$parseRule(peg$startRuleIndex);

    if (peg$result !== peg$FAILED && peg$currPos === input.length) {
      return peg$result;
    } else {
      if (peg$result !== peg$FAILED && peg$currPos < input.length) {
        peg$fail(peg$endExpectation());
      }

      throw peg$buildStructuredError(
        peg$maxFailExpected,
        peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null,
        peg$maxFailPos < input.length
          ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1)
          : peg$computeLocation(peg$maxFailPos, peg$maxFailPos)
      );
    }
  }

  return {
    SyntaxError: peg$SyntaxError,
    parse:       peg$parse
  };
})();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants