'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

// Generated by Peggy 1.2.0.
//
// https://peggyjs.org/
function peg$subclass(child, parent) {
  function C() {
    this.constructor = child;
  }

  C.prototype = parent.prototype;
  child.prototype = new C();
}

function peg$SyntaxError(message, expected, found, location) {
  var self = Error.call(this, message);

  if (Object.setPrototypeOf) {
    Object.setPrototypeOf(self, peg$SyntaxError.prototype);
  }

  self.expected = expected;
  self.found = found;
  self.location = location;
  self.name = "SyntaxError";
  return self;
}

peg$subclass(peg$SyntaxError, Error);

function peg$padEnd(str, targetLength, padString) {
  padString = padString || " ";

  if (str.length > targetLength) {
    return str;
  }

  targetLength -= str.length;
  padString += padString.repeat(targetLength);
  return str + padString.slice(0, targetLength);
}

peg$SyntaxError.prototype.format = function (sources) {
  var str = "Error: " + this.message;

  if (this.location) {
    var src = null;
    var k;

    for (k = 0; k < sources.length; k++) {
      if (sources[k].source === this.location.source) {
        src = sources[k].text.split(/\r\n|\n|\r/g);
        break;
      }
    }

    var s = this.location.start;
    var loc = this.location.source + ":" + s.line + ":" + s.column;

    if (src) {
      var e = this.location.end;
      var filler = peg$padEnd("", s.line.toString().length);
      var line = src[s.line - 1];
      var last = s.line === e.line ? e.column : line.length + 1;
      str += "\n --> " + loc + "\n" + filler + " |\n" + s.line + " | " + line + "\n" + filler + " | " + peg$padEnd("", s.column - 1) + peg$padEnd("", last - s.column, "^");
    } else {
      str += "\n at " + loc;
    }
  }

  return str;
};

peg$SyntaxError.buildMessage = function (expected, found) {
  var DESCRIBE_EXPECTATION_FNS = {
    literal: function (expectation) {
      return "\"" + literalEscape(expectation.text) + "\"";
    },
    class: function (expectation) {
      var escapedParts = expectation.parts.map(function (part) {
        return Array.isArray(part) ? classEscape(part[0]) + "-" + classEscape(part[1]) : classEscape(part);
      });
      return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]";
    },
    any: function () {
      return "any character";
    },
    end: function () {
      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 = expected.map(describeExpectation);
    var i, j;
    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 !== undefined ? options : {};
  var peg$FAILED = {};
  var peg$source = options.grammarSource;
  var peg$startRuleFunctions = {
    JSONPath: peg$parseJSONPath
  };
  var peg$startRuleFunction = peg$parseJSONPath;
  var peg$c0 = "$";
  var peg$c1 = "[";
  var peg$c2 = "]";
  var peg$c4 = "..";
  var peg$c5 = "(";
  var peg$c6 = ")";
  var peg$c7 = "?(";
  var peg$c8 = ":";
  var peg$c9 = "@";
  var peg$c10 = "()";
  var peg$c11 = "~";
  var peg$c12 = "^";
  var peg$c13 = ".";
  var peg$c14 = "\"";
  var peg$c15 = "'";
  var peg$c16 = "-";
  var peg$c17 = "*";
  var peg$c18 = ".length";
  var peg$r0 = /^[a-z]/;
  var peg$r1 = /^[@[]/;
  var peg$r2 = /^[$_\-]/;
  var peg$r3 = /^[^"]/;
  var peg$r4 = /^[^']/;
  var peg$r5 = /^[A-Za-z]/;
  var peg$r6 = /^[0-9]/;
  var peg$r7 = /^[ \t]/;
  var peg$r8 = /^["]/;
  var peg$r9 = /^[']/;
  var peg$r10 = /^[ $@.,_=<>!|&+~%\^*\/;\-[\]]/;
  var peg$e0 = peg$literalExpectation("$", false);
  var peg$e1 = peg$literalExpectation("[", false);
  var peg$e2 = peg$literalExpectation("]", false);
  var peg$e3 = peg$literalExpectation(",", false);
  var peg$e4 = peg$literalExpectation("..", false);
  var peg$e5 = peg$literalExpectation("(", false);
  var peg$e6 = peg$literalExpectation(")", false);
  var peg$e7 = peg$literalExpectation("?(", false);
  var peg$e8 = peg$literalExpectation(":", false);
  var peg$e9 = peg$literalExpectation("@", false);
  var peg$e10 = peg$classExpectation([["a", "z"]], false, false);
  var peg$e11 = peg$literalExpectation("()", false);
  var peg$e12 = peg$literalExpectation("~", false);
  var peg$e13 = peg$literalExpectation("^", false);
  var peg$e14 = peg$literalExpectation(".", false);
  var peg$e15 = peg$classExpectation(["@", "["], false, false);
  var peg$e16 = peg$classExpectation(["$", "_", "-"], false, false);
  var peg$e17 = peg$literalExpectation("\"", false);
  var peg$e18 = peg$classExpectation(["\""], true, false);
  var peg$e19 = peg$literalExpectation("'", false);
  var peg$e20 = peg$classExpectation(["'"], true, false);
  var peg$e21 = peg$literalExpectation("-", false);
  var peg$e22 = peg$literalExpectation("*", false);
  var peg$e23 = peg$classExpectation([["A", "Z"], ["a", "z"]], false, false);
  var peg$e24 = peg$classExpectation([["0", "9"]], false, false);
  var peg$e25 = peg$classExpectation([" ", "\t"], false, false);
  var peg$e26 = peg$classExpectation(["\""], false, false);
  var peg$e27 = peg$classExpectation(["'"], false, false);
  var peg$e28 = peg$classExpectation([" ", "$", "@", ".", ",", "_", "=", "<", ">", "!", "|", "&", "+", "~", "%", "^", "*", "/", ";", "-", "[", "]"], false, false);
  var peg$e29 = peg$literalExpectation(".length", false);

  var peg$f0 = function (deep, step) {
    return { ...step,
      deep
    };
  };

  var peg$f1 = function (nodes, modifiers) {
    return nodes.concat(Array.isArray(modifiers) ? modifiers : modifiers === null ? [] : modifiers);
  };

  var peg$f2 = function () {
    return {
      type: "WildcardExpression"
    };
  };

  var peg$f3 = function (expression) {
    return expression;
  };

  var peg$f4 = function (value) {
    return value;
  };

  var peg$f5 = function (value) {
    return {
      type: "MultipleMemberExpression",
      value: [...new Set(value)]
    };
  };

  var peg$f6 = function () {
    return /^\$\.{2}[~^]*$/.test(input);
  };

  var peg$f7 = function () {
    return {
      type: 'AllParentExpression'
    };
  };

  var peg$f8 = function (value) {
    return {
      type: "MemberExpression",
      value
    };
  };

  var peg$f9 = function (value) {
    return {
      type: "ScriptFilterExpression",
      value
    };
  };

  var peg$f10 = function (value) {
    return {
      type: "SliceExpression",
      value: value.split(':').reduce((values, val, i) => {
        if (val !== '') values[i] = Number(val);
        return values;
      }, [0, Infinity, 1])
    };
  };

  var peg$f11 = function (value) {
    return {
      type: 'ScriptFilterExpression',
      value
    };
  };

  var peg$f12 = function (node) {
    return node.value;
  };

  var peg$f13 = function () {
    return {
      type: "KeyExpression"
    };
  };

  var peg$f14 = function () {
    return {
      type: "ParentExpression"
    };
  };

  var peg$f15 = function () {
    return true;
  };

  var peg$f16 = function () {
    return false;
  };

  var peg$f17 = function (value) {
    return value.length > 0 && Number.isSafeInteger(Number(value)) ? Number(value) : value;
  };

  var peg$f18 = function () {
    return text().slice(1, -1);
  };

  var peg$f19 = function () {
    return Number(text());
  };

  var peg$f20 = function (value) {
    return {
      type: "SliceExpression",
      value: [-value, Infinity, 1]
    };
  };

  var peg$currPos = 0;
  var peg$savedPos = 0;
  var peg$posDetailsCache = [{
    line: 1,
    column: 1
  }];
  var peg$maxFailPos = 0;
  var peg$maxFailExpected = [];
  var peg$silentFails = 0;
  var 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$savedPos, peg$currPos);
  }

  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$endExpectation() {
    return {
      type: "end"
    };
  }

  function peg$computePosDetails(pos) {
    var details = peg$posDetailsCache[pos];
    var 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);
    var endPosDetails = peg$computePosDetails(endPos);
    return {
      source: peg$source,
      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$buildStructuredError(expected, found, location) {
    return new peg$SyntaxError(peg$SyntaxError.buildMessage(expected, found), expected, found, location);
  }

  function peg$parseJSONPath() {
    var s0, s1, s2, s3, s4, s5;
    s0 = peg$currPos;
    s1 = peg$parseRoot();

    if (s1 !== peg$FAILED) {
      s2 = [];
      s3 = peg$parseAllParentExpression();

      if (s3 === peg$FAILED) {
        s3 = peg$currPos;
        s4 = peg$parseDescendant();

        if (s4 !== peg$FAILED) {
          s5 = peg$parseNode();

          if (s5 !== peg$FAILED) {
            peg$savedPos = s3;
            s3 = peg$f0(s4, s5);
          } else {
            peg$currPos = s3;
            s3 = peg$FAILED;
          }
        } else {
          peg$currPos = s3;
          s3 = peg$FAILED;
        }
      }

      while (s3 !== peg$FAILED) {
        s2.push(s3);
        s3 = peg$parseAllParentExpression();

        if (s3 === peg$FAILED) {
          s3 = peg$currPos;
          s4 = peg$parseDescendant();

          if (s4 !== peg$FAILED) {
            s5 = peg$parseNode();

            if (s5 !== peg$FAILED) {
              peg$savedPos = s3;
              s3 = peg$f0(s4, s5);
            } else {
              peg$currPos = s3;
              s3 = peg$FAILED;
            }
          } else {
            peg$currPos = s3;
            s3 = peg$FAILED;
          }
        }
      }

      s3 = [];
      s4 = peg$parseModifier();

      if (s4 !== peg$FAILED) {
        while (s4 !== peg$FAILED) {
          s3.push(s4);
          s4 = peg$parseModifier();
        }
      } else {
        s3 = peg$FAILED;
      }

      if (s3 === peg$FAILED) {
        s3 = null;
      }

      peg$savedPos = s0;
      s0 = peg$f1(s2, s3);
    } else {
      peg$currPos = s0;
      s0 = peg$FAILED;
    }

    return s0;
  }

  function peg$parseRoot() {
    var s0;

    if (input.charCodeAt(peg$currPos) === 36) {
      s0 = peg$c0;
      peg$currPos++;
    } else {
      s0 = peg$FAILED;

      if (peg$silentFails === 0) {
        peg$fail(peg$e0);
      }
    }

    return s0;
  }

  function peg$parseNode() {
    var s0, s1, s2, s3, s4;
    s0 = peg$parseMemberExpression();

    if (s0 === peg$FAILED) {
      s0 = peg$currPos;
      s1 = peg$parseWildcard();

      if (s1 === peg$FAILED) {
        s1 = peg$currPos;

        if (input.charCodeAt(peg$currPos) === 91) {
          s2 = peg$c1;
          peg$currPos++;
        } else {
          s2 = peg$FAILED;

          if (peg$silentFails === 0) {
            peg$fail(peg$e1);
          }
        }

        if (s2 !== peg$FAILED) {
          s3 = peg$parseWildcard();

          if (s3 !== peg$FAILED) {
            if (input.charCodeAt(peg$currPos) === 93) {
              s4 = peg$c2;
              peg$currPos++;
            } else {
              s4 = peg$FAILED;

              if (peg$silentFails === 0) {
                peg$fail(peg$e2);
              }
            }

            if (s4 !== peg$FAILED) {
              s2 = [s2, s3, s4];
              s1 = s2;
            } else {
              peg$currPos = s1;
              s1 = peg$FAILED;
            }
          } else {
            peg$currPos = s1;
            s1 = peg$FAILED;
          }
        } else {
          peg$currPos = s1;
          s1 = peg$FAILED;
        }
      }

      if (s1 !== peg$FAILED) {
        peg$savedPos = s0;
        s1 = peg$f2();
      }

      s0 = s1;

      if (s0 === peg$FAILED) {
        s0 = peg$currPos;

        if (input.charCodeAt(peg$currPos) === 91) {
          s1 = peg$c1;
          peg$currPos++;
        } else {
          s1 = peg$FAILED;

          if (peg$silentFails === 0) {
            peg$fail(peg$e1);
          }
        }

        if (s1 !== peg$FAILED) {
          s2 = peg$parseScriptExpression();

          if (s2 !== peg$FAILED) {
            if (input.charCodeAt(peg$currPos) === 93) {
              s3 = peg$c2;
              peg$currPos++;
            } else {
              s3 = peg$FAILED;

              if (peg$silentFails === 0) {
                peg$fail(peg$e2);
              }
            }

            if (s3 !== peg$FAILED) {
              peg$savedPos = s0;
              s0 = peg$f3(s2);
            } else {
              peg$currPos = s0;
              s0 = peg$FAILED;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$FAILED;
          }
        } else {
          peg$currPos = s0;
          s0 = peg$FAILED;
        }

        if (s0 === peg$FAILED) {
          s0 = peg$currPos;

          if (input.charCodeAt(peg$currPos) === 91) {
            s1 = peg$c1;
            peg$currPos++;
          } else {
            s1 = peg$FAILED;

            if (peg$silentFails === 0) {
              peg$fail(peg$e1);
            }
          }

          if (s1 !== peg$FAILED) {
            s2 = peg$parseScriptFilterExpression();

            if (s2 !== peg$FAILED) {
              if (input.charCodeAt(peg$currPos) === 93) {
                s3 = peg$c2;
                peg$currPos++;
              } else {
                s3 = peg$FAILED;

                if (peg$silentFails === 0) {
                  peg$fail(peg$e2);
                }
              }

              if (s3 !== peg$FAILED) {
                peg$savedPos = s0;
                s0 = peg$f3(s2);
              } else {
                peg$currPos = s0;
                s0 = peg$FAILED;
              }
            } else {
              peg$currPos = s0;
              s0 = peg$FAILED;
            }
          } else {
            peg$currPos = s0;
            s0 = peg$FAILED;
          }

          if (s0 === peg$FAILED) {
            s0 = peg$currPos;
            s1 = peg$parseJsonPathPlusFilterFunction();

            if (s1 === peg$FAILED) {
              s1 = peg$parseCustomScriptFilterExpression();
            }

            if (s1 !== peg$FAILED) {
              peg$savedPos = s0;
              s1 = peg$f3(s1);
            }

            s0 = s1;

            if (s0 === peg$FAILED) {
              s0 = peg$currPos;

              if (input.charCodeAt(peg$currPos) === 91) {
                s1 = peg$c1;
                peg$currPos++;
              } else {
                s1 = peg$FAILED;

                if (peg$silentFails === 0) {
                  peg$fail(peg$e1);
                }
              }

              if (s1 !== peg$FAILED) {
                s2 = [];
                s3 = peg$currPos;
                s4 = peg$parseMemberIdentifier();

                if (s4 !== peg$FAILED) {
                  if (input.charCodeAt(peg$currPos) === 44) {
                    peg$currPos++;
                  } else {

                    if (peg$silentFails === 0) {
                      peg$fail(peg$e3);
                    }
                  }

                  peg$savedPos = s3;
                  s3 = peg$f4(s4);
                } else {
                  peg$currPos = s3;
                  s3 = peg$FAILED;
                }

                while (s3 !== peg$FAILED) {
                  s2.push(s3);
                  s3 = peg$currPos;
                  s4 = peg$parseMemberIdentifier();

                  if (s4 !== peg$FAILED) {
                    if (input.charCodeAt(peg$currPos) === 44) {
                      peg$currPos++;
                    } else {

                      if (peg$silentFails === 0) {
                        peg$fail(peg$e3);
                      }
                    }

                    peg$savedPos = s3;
                    s3 = peg$f4(s4);
                  } else {
                    peg$currPos = s3;
                    s3 = peg$FAILED;
                  }
                }

                if (input.charCodeAt(peg$currPos) === 93) {
                  s3 = peg$c2;
                  peg$currPos++;
                } else {
                  s3 = peg$FAILED;

                  if (peg$silentFails === 0) {
                    peg$fail(peg$e2);
                  }
                }

                if (s3 !== peg$FAILED) {
                  peg$savedPos = s0;
                  s0 = peg$f5(s2);
                } else {
                  peg$currPos = s0;
                  s0 = peg$FAILED;
                }
              } else {
                peg$currPos = s0;
                s0 = peg$FAILED;
              }

              if (s0 === peg$FAILED) {
                s0 = peg$currPos;

                if (input.charCodeAt(peg$currPos) === 91) {
                  s1 = peg$c1;
                  peg$currPos++;
                } else {
                  s1 = peg$FAILED;

                  if (peg$silentFails === 0) {
                    peg$fail(peg$e1);
                  }
                }

                if (s1 !== peg$FAILED) {
                  s2 = peg$parseSliceExpression();

                  if (s2 !== peg$FAILED) {
                    if (input.charCodeAt(peg$currPos) === 93) {
                      s3 = peg$c2;
                      peg$currPos++;
                    } else {
                      s3 = peg$FAILED;

                      if (peg$silentFails === 0) {
                        peg$fail(peg$e2);
                      }
                    }

                    if (s3 !== peg$FAILED) {
                      peg$savedPos = s0;
                      s0 = peg$f3(s2);
                    } else {
                      peg$currPos = s0;
                      s0 = peg$FAILED;
                    }
                  } else {
                    peg$currPos = s0;
                    s0 = peg$FAILED;
                  }
                } else {
                  peg$currPos = s0;
                  s0 = peg$FAILED;
                }
              }
            }
          }
        }
      }
    }

    return s0;
  }

  function peg$parseAllParentExpression() {
    var s0, s1, s2;
    s0 = peg$currPos;
    peg$savedPos = peg$currPos;
    s1 = peg$f6();

    if (s1) {
      s1 = undefined;
    } else {
      s1 = peg$FAILED;
    }

    if (s1 !== peg$FAILED) {
      if (input.substr(peg$currPos, 2) === peg$c4) {
        s2 = peg$c4;
        peg$currPos += 2;
      } else {
        s2 = peg$FAILED;

        if (peg$silentFails === 0) {
          peg$fail(peg$e4);
        }
      }

      if (s2 !== peg$FAILED) {
        peg$savedPos = s0;
        s0 = peg$f7();
      } else {
        peg$currPos = s0;
        s0 = peg$FAILED;
      }
    } else {
      peg$currPos = s0;
      s0 = peg$FAILED;
    }

    return s0;
  }

  function peg$parseMemberExpression() {
    var s0, s1, s2, s3, s4;
    s0 = peg$currPos;
    s1 = peg$parseIdentifier();

    if (s1 === peg$FAILED) {
      s1 = peg$currPos;

      if (input.charCodeAt(peg$currPos) === 91) {
        s2 = peg$c1;
        peg$currPos++;
      } else {
        s2 = peg$FAILED;

        if (peg$silentFails === 0) {
          peg$fail(peg$e1);
        }
      }

      if (s2 !== peg$FAILED) {
        s3 = peg$parseMemberIdentifier();

        if (s3 !== peg$FAILED) {
          if (input.charCodeAt(peg$currPos) === 93) {
            s4 = peg$c2;
            peg$currPos++;
          } else {
            s4 = peg$FAILED;

            if (peg$silentFails === 0) {
              peg$fail(peg$e2);
            }
          }

          if (s4 !== peg$FAILED) {
            peg$savedPos = s1;
            s1 = peg$f4(s3);
          } else {
            peg$currPos = s1;
            s1 = peg$FAILED;
          }
        } else {
          peg$currPos = s1;
          s1 = peg$FAILED;
        }
      } else {
        peg$currPos = s1;
        s1 = peg$FAILED;
      }
    }

    if (s1 !== peg$FAILED) {
      peg$savedPos = s0;
      s1 = peg$f8(s1);
    }

    s0 = s1;
    return s0;
  }

  function peg$parseScriptExpression() {
    var s0, s1, s2, s3;
    s0 = peg$currPos;

    if (input.charCodeAt(peg$currPos) === 40) {
      s1 = peg$c5;
      peg$currPos++;
    } else {
      s1 = peg$FAILED;

      if (peg$silentFails === 0) {
        peg$fail(peg$e5);
      }
    }

    if (s1 !== peg$FAILED) {
      s2 = peg$parseEvalExpression();

      if (s2 !== peg$FAILED) {
        if (input.charCodeAt(peg$currPos) === 41) {
          s3 = peg$c6;
          peg$currPos++;
        } else {
          s3 = peg$FAILED;

          if (peg$silentFails === 0) {
            peg$fail(peg$e6);
          }
        }

        if (s3 !== peg$FAILED) {
          peg$savedPos = s0;
          s0 = peg$f4(s2);
        } else {
          peg$currPos = s0;
          s0 = peg$FAILED;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$FAILED;
      }
    } else {
      peg$currPos = s0;
      s0 = peg$FAILED;
    }

    return s0;
  }

  function peg$parseScriptFilterExpression() {
    var s0, s1, s2, s3;
    s0 = peg$currPos;

    if (input.substr(peg$currPos, 2) === peg$c7) {
      s1 = peg$c7;
      peg$currPos += 2;
    } else {
      s1 = peg$FAILED;

      if (peg$silentFails === 0) {
        peg$fail(peg$e7);
      }
    }

    if (s1 !== peg$FAILED) {
      s2 = peg$parseJSScript();

      if (s2 !== peg$FAILED) {
        if (input.charCodeAt(peg$currPos) === 41) {
          s3 = peg$c6;
          peg$currPos++;
        } else {
          s3 = peg$FAILED;

          if (peg$silentFails === 0) {
            peg$fail(peg$e6);
          }
        }

        if (s3 !== peg$FAILED) {
          peg$savedPos = s0;
          s0 = peg$f9(s2);
        } else {
          peg$currPos = s0;
          s0 = peg$FAILED;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$FAILED;
      }
    } else {
      peg$currPos = s0;
      s0 = peg$FAILED;
    }

    return s0;
  }

  function peg$parseSliceExpression() {
    var s0, s1, s2, s3, s4, s5, s6;
    s0 = peg$currPos;
    s1 = peg$currPos;
    s2 = peg$currPos;
    s3 = peg$currPos;
    s4 = peg$parseNumber();

    if (s4 !== peg$FAILED) {
      if (input.charCodeAt(peg$currPos) === 58) {
        s5 = peg$c8;
        peg$currPos++;
      } else {
        s5 = peg$FAILED;

        if (peg$silentFails === 0) {
          peg$fail(peg$e8);
        }
      }

      if (s5 !== peg$FAILED) {
        s6 = peg$parseNumber();

        if (s6 === peg$FAILED) {
          s6 = null;
        }

        s4 = [s4, s5, s6];
        s3 = s4;
      } else {
        peg$currPos = s3;
        s3 = peg$FAILED;
      }
    } else {
      peg$currPos = s3;
      s3 = peg$FAILED;
    }

    if (s3 === peg$FAILED) {
      s3 = peg$currPos;

      if (input.charCodeAt(peg$currPos) === 58) {
        s4 = peg$c8;
        peg$currPos++;
      } else {
        s4 = peg$FAILED;

        if (peg$silentFails === 0) {
          peg$fail(peg$e8);
        }
      }

      if (s4 !== peg$FAILED) {
        s5 = peg$parseNumber();

        if (s5 === peg$FAILED) {
          s5 = null;
        }

        s4 = [s4, s5];
        s3 = s4;
      } else {
        peg$currPos = s3;
        s3 = peg$FAILED;
      }

      if (s3 === peg$FAILED) {
        s3 = peg$parseNumber();
      }
    }

    if (s3 !== peg$FAILED) {
      s4 = peg$currPos;

      if (input.charCodeAt(peg$currPos) === 58) {
        s5 = peg$c8;
        peg$currPos++;
      } else {
        s5 = peg$FAILED;

        if (peg$silentFails === 0) {
          peg$fail(peg$e8);
        }
      }

      if (s5 !== peg$FAILED) {
        s6 = peg$parseNumber();

        if (s6 !== peg$FAILED) {
          s5 = [s5, s6];
          s4 = s5;
        } else {
          peg$currPos = s4;
          s4 = peg$FAILED;
        }
      } else {
        peg$currPos = s4;
        s4 = peg$FAILED;
      }

      if (s4 === peg$FAILED) {
        s4 = null;
      }

      s3 = [s3, s4];
      s2 = s3;
    } else {
      peg$currPos = s2;
      s2 = peg$FAILED;
    }

    if (s2 !== peg$FAILED) {
      s1 = input.substring(s1, peg$currPos);
    } else {
      s1 = s2;
    }

    if (s1 !== peg$FAILED) {
      peg$savedPos = s0;
      s1 = peg$f10(s1);
    }

    s0 = s1;
    return s0;
  }

  function peg$parseJsonPathPlusFilterFunction() {
    var s0, s1, s2, s3, s4, s5;
    s0 = peg$currPos;
    s1 = peg$currPos;
    s2 = peg$currPos;

    if (input.charCodeAt(peg$currPos) === 64) {
      s3 = peg$c9;
      peg$currPos++;
    } else {
      s3 = peg$FAILED;

      if (peg$silentFails === 0) {
        peg$fail(peg$e9);
      }
    }

    if (s3 !== peg$FAILED) {
      s4 = [];

      if (peg$r0.test(input.charAt(peg$currPos))) {
        s5 = input.charAt(peg$currPos);
        peg$currPos++;
      } else {
        s5 = peg$FAILED;

        if (peg$silentFails === 0) {
          peg$fail(peg$e10);
        }
      }

      if (s5 !== peg$FAILED) {
        while (s5 !== peg$FAILED) {
          s4.push(s5);

          if (peg$r0.test(input.charAt(peg$currPos))) {
            s5 = input.charAt(peg$currPos);
            peg$currPos++;
          } else {
            s5 = peg$FAILED;

            if (peg$silentFails === 0) {
              peg$fail(peg$e10);
            }
          }
        }
      } else {
        s4 = peg$FAILED;
      }

      if (s4 !== peg$FAILED) {
        if (input.substr(peg$currPos, 2) === peg$c10) {
          s5 = peg$c10;
          peg$currPos += 2;
        } else {
          s5 = peg$FAILED;

          if (peg$silentFails === 0) {
            peg$fail(peg$e11);
          }
        }

        if (s5 !== peg$FAILED) {
          s3 = [s3, s4, s5];
          s2 = s3;
        } else {
          peg$currPos = s2;
          s2 = peg$FAILED;
        }
      } else {
        peg$currPos = s2;
        s2 = peg$FAILED;
      }
    } else {
      peg$currPos = s2;
      s2 = peg$FAILED;
    }

    if (s2 !== peg$FAILED) {
      s1 = input.substring(s1, peg$currPos);
    } else {
      s1 = s2;
    }

    if (s1 !== peg$FAILED) {
      peg$savedPos = s0;
      s1 = peg$f11(s1);
    }

    s0 = s1;
    return s0;
  }

  function peg$parseCustomScriptFilterExpression() {
    var s0, s1, s2, s3, s4;
    s0 = peg$currPos;
    s1 = peg$currPos;
    s2 = peg$currPos;

    if (input.charCodeAt(peg$currPos) === 64) {
      s3 = peg$c9;
      peg$currPos++;
    } else {
      s3 = peg$FAILED;

      if (peg$silentFails === 0) {
        peg$fail(peg$e9);
      }
    }

    if (s3 !== peg$FAILED) {
      s4 = peg$parseJsonPathPlusFilterFunction();

      if (s4 !== peg$FAILED) {
        peg$savedPos = s2;
        s2 = peg$f12(s4);
      } else {
        peg$currPos = s2;
        s2 = peg$FAILED;
      }
    } else {
      peg$currPos = s2;
      s2 = peg$FAILED;
    }

    if (s2 !== peg$FAILED) {
      s1 = input.substring(s1, peg$currPos);
    } else {
      s1 = s2;
    }

    if (s1 !== peg$FAILED) {
      peg$savedPos = s0;
      s1 = peg$f11(s1);
    }

    s0 = s1;
    return s0;
  }

  function peg$parseKeyExpression() {
    var s0, s1;
    s0 = peg$currPos;

    if (input.charCodeAt(peg$currPos) === 126) {
      s1 = peg$c11;
      peg$currPos++;
    } else {
      s1 = peg$FAILED;

      if (peg$silentFails === 0) {
        peg$fail(peg$e12);
      }
    }

    if (s1 !== peg$FAILED) {
      peg$savedPos = s0;
      s1 = peg$f13();
    }

    s0 = s1;
    return s0;
  }

  function peg$parseParentExpression() {
    var s0, s1;
    s0 = peg$currPos;

    if (input.charCodeAt(peg$currPos) === 94) {
      s1 = peg$c12;
      peg$currPos++;
    } else {
      s1 = peg$FAILED;

      if (peg$silentFails === 0) {
        peg$fail(peg$e13);
      }
    }

    if (s1 !== peg$FAILED) {
      peg$savedPos = s0;
      s1 = peg$f14();
    }

    s0 = s1;
    return s0;
  }

  function peg$parseModifier() {
    var s0;
    s0 = peg$parseKeyExpression();

    if (s0 === peg$FAILED) {
      s0 = peg$parseParentExpression();
    }

    return s0;
  }

  function peg$parseDescendant() {
    var s0, s1, s2, s3;
    s0 = peg$currPos;

    if (input.substr(peg$currPos, 2) === peg$c4) {
      s1 = peg$c4;
      peg$currPos += 2;
    } else {
      s1 = peg$FAILED;

      if (peg$silentFails === 0) {
        peg$fail(peg$e4);
      }
    }

    if (s1 !== peg$FAILED) {
      peg$savedPos = s0;
      s1 = peg$f15();
    }

    s0 = s1;

    if (s0 === peg$FAILED) {
      s0 = peg$currPos;

      if (input.charCodeAt(peg$currPos) === 46) {
        s1 = peg$c13;
        peg$currPos++;
      } else {
        s1 = peg$FAILED;

        if (peg$silentFails === 0) {
          peg$fail(peg$e14);
        }
      }

      if (s1 !== peg$FAILED) {
        s2 = peg$currPos;
        peg$silentFails++;

        if (input.charCodeAt(peg$currPos) === 91) {
          s3 = peg$c1;
          peg$currPos++;
        } else {
          s3 = peg$FAILED;

          if (peg$silentFails === 0) {
            peg$fail(peg$e1);
          }
        }

        peg$silentFails--;

        if (s3 !== peg$FAILED) {
          peg$currPos = s2;
          s2 = undefined;
        } else {
          s2 = peg$FAILED;
        }

        if (s2 !== peg$FAILED) {
          peg$savedPos = s0;
          s0 = peg$f15();
        } else {
          peg$currPos = s0;
          s0 = peg$FAILED;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$FAILED;
      }

      if (s0 === peg$FAILED) {
        s0 = peg$currPos;

        if (input.charCodeAt(peg$currPos) === 46) {
          s1 = peg$c13;
          peg$currPos++;
        } else {
          s1 = peg$FAILED;

          if (peg$silentFails === 0) {
            peg$fail(peg$e14);
          }
        }

        if (s1 !== peg$FAILED) {
          peg$savedPos = s0;
          s1 = peg$f16();
        }

        s0 = s1;

        if (s0 === peg$FAILED) {
          s0 = peg$currPos;
          s1 = peg$currPos;
          peg$silentFails++;

          if (peg$r1.test(input.charAt(peg$currPos))) {
            s2 = input.charAt(peg$currPos);
            peg$currPos++;
          } else {
            s2 = peg$FAILED;

            if (peg$silentFails === 0) {
              peg$fail(peg$e15);
            }
          }

          peg$silentFails--;

          if (s2 !== peg$FAILED) {
            peg$currPos = s1;
            s1 = undefined;
          } else {
            s1 = peg$FAILED;
          }

          if (s1 !== peg$FAILED) {
            peg$savedPos = s0;
            s1 = peg$f16();
          }

          s0 = s1;
        }
      }
    }

    return s0;
  }

  function peg$parseIdentifier() {
    var s0, s1, s2;
    s0 = peg$currPos;
    s1 = [];

    if (peg$r2.test(input.charAt(peg$currPos))) {
      s2 = input.charAt(peg$currPos);
      peg$currPos++;
    } else {
      s2 = peg$FAILED;

      if (peg$silentFails === 0) {
        peg$fail(peg$e16);
      }
    }

    if (s2 === peg$FAILED) {
      s2 = peg$parseChar();

      if (s2 === peg$FAILED) {
        s2 = peg$parseDigit();
      }
    }

    if (s2 !== peg$FAILED) {
      while (s2 !== peg$FAILED) {
        s1.push(s2);

        if (peg$r2.test(input.charAt(peg$currPos))) {
          s2 = input.charAt(peg$currPos);
          peg$currPos++;
        } else {
          s2 = peg$FAILED;

          if (peg$silentFails === 0) {
            peg$fail(peg$e16);
          }
        }

        if (s2 === peg$FAILED) {
          s2 = peg$parseChar();

          if (s2 === peg$FAILED) {
            s2 = peg$parseDigit();
          }
        }
      }
    } else {
      s1 = peg$FAILED;
    }

    if (s1 !== peg$FAILED) {
      s0 = input.substring(s0, peg$currPos);
    } else {
      s0 = s1;
    }

    return s0;
  }

  function peg$parseMemberIdentifier() {
    var s0, s1, s2, s3, s4, s5;
    s0 = peg$currPos;
    s1 = peg$parseIdentifier();

    if (s1 !== peg$FAILED) {
      peg$savedPos = s0;
      s1 = peg$f17(s1);
    }

    s0 = s1;

    if (s0 === peg$FAILED) {
      s0 = peg$currPos;
      s1 = peg$currPos;

      if (input.charCodeAt(peg$currPos) === 34) {
        s2 = peg$c14;
        peg$currPos++;
      } else {
        s2 = peg$FAILED;

        if (peg$silentFails === 0) {
          peg$fail(peg$e17);
        }
      }

      if (s2 !== peg$FAILED) {
        s3 = peg$currPos;
        s4 = [];

        if (peg$r3.test(input.charAt(peg$currPos))) {
          s5 = input.charAt(peg$currPos);
          peg$currPos++;
        } else {
          s5 = peg$FAILED;

          if (peg$silentFails === 0) {
            peg$fail(peg$e18);
          }
        }

        while (s5 !== peg$FAILED) {
          s4.push(s5);

          if (peg$r3.test(input.charAt(peg$currPos))) {
            s5 = input.charAt(peg$currPos);
            peg$currPos++;
          } else {
            s5 = peg$FAILED;

            if (peg$silentFails === 0) {
              peg$fail(peg$e18);
            }
          }
        }

        s3 = input.substring(s3, peg$currPos);

        if (input.charCodeAt(peg$currPos) === 34) {
          s4 = peg$c14;
          peg$currPos++;
        } else {
          s4 = peg$FAILED;

          if (peg$silentFails === 0) {
            peg$fail(peg$e17);
          }
        }

        if (s4 !== peg$FAILED) {
          s2 = [s2, s3, s4];
          s1 = s2;
        } else {
          peg$currPos = s1;
          s1 = peg$FAILED;
        }
      } else {
        peg$currPos = s1;
        s1 = peg$FAILED;
      }

      if (s1 === peg$FAILED) {
        s1 = peg$currPos;

        if (input.charCodeAt(peg$currPos) === 39) {
          s2 = peg$c15;
          peg$currPos++;
        } else {
          s2 = peg$FAILED;

          if (peg$silentFails === 0) {
            peg$fail(peg$e19);
          }
        }

        if (s2 !== peg$FAILED) {
          s3 = peg$currPos;
          s4 = [];

          if (peg$r4.test(input.charAt(peg$currPos))) {
            s5 = input.charAt(peg$currPos);
            peg$currPos++;
          } else {
            s5 = peg$FAILED;

            if (peg$silentFails === 0) {
              peg$fail(peg$e20);
            }
          }

          while (s5 !== peg$FAILED) {
            s4.push(s5);

            if (peg$r4.test(input.charAt(peg$currPos))) {
              s5 = input.charAt(peg$currPos);
              peg$currPos++;
            } else {
              s5 = peg$FAILED;

              if (peg$silentFails === 0) {
                peg$fail(peg$e20);
              }
            }
          }

          s3 = input.substring(s3, peg$currPos);

          if (input.charCodeAt(peg$currPos) === 39) {
            s4 = peg$c15;
            peg$currPos++;
          } else {
            s4 = peg$FAILED;

            if (peg$silentFails === 0) {
              peg$fail(peg$e19);
            }
          }

          if (s4 !== peg$FAILED) {
            s2 = [s2, s3, s4];
            s1 = s2;
          } else {
            peg$currPos = s1;
            s1 = peg$FAILED;
          }
        } else {
          peg$currPos = s1;
          s1 = peg$FAILED;
        }
      }

      if (s1 !== peg$FAILED) {
        peg$savedPos = s0;
        s1 = peg$f18();
      }

      s0 = s1;
    }

    return s0;
  }

  function peg$parseNumber() {
    var s0, s2, s3;
    s0 = peg$currPos;

    if (input.charCodeAt(peg$currPos) === 45) {
      peg$currPos++;
    } else {

      if (peg$silentFails === 0) {
        peg$fail(peg$e21);
      }
    }

    s2 = [];
    s3 = peg$parseDigit();

    if (s3 !== peg$FAILED) {
      while (s3 !== peg$FAILED) {
        s2.push(s3);
        s3 = peg$parseDigit();
      }
    } else {
      s2 = peg$FAILED;
    }

    if (s2 !== peg$FAILED) {
      peg$savedPos = s0;
      s0 = peg$f19();
    } else {
      peg$currPos = s0;
      s0 = peg$FAILED;
    }

    return s0;
  }

  function peg$parseWildcard() {
    var s0;

    if (input.charCodeAt(peg$currPos) === 42) {
      s0 = peg$c17;
      peg$currPos++;
    } else {
      s0 = peg$FAILED;

      if (peg$silentFails === 0) {
        peg$fail(peg$e22);
      }
    }

    return s0;
  }

  function peg$parseChar() {
    var s0;

    if (peg$r5.test(input.charAt(peg$currPos))) {
      s0 = input.charAt(peg$currPos);
      peg$currPos++;
    } else {
      s0 = peg$FAILED;

      if (peg$silentFails === 0) {
        peg$fail(peg$e23);
      }
    }

    return s0;
  }

  function peg$parseDigit() {
    var s0;

    if (peg$r6.test(input.charAt(peg$currPos))) {
      s0 = input.charAt(peg$currPos);
      peg$currPos++;
    } else {
      s0 = peg$FAILED;

      if (peg$silentFails === 0) {
        peg$fail(peg$e24);
      }
    }

    return s0;
  }

  function peg$parseSpace() {
    var s0;

    if (peg$r7.test(input.charAt(peg$currPos))) {
      s0 = input.charAt(peg$currPos);
      peg$currPos++;
    } else {
      s0 = peg$FAILED;

      if (peg$silentFails === 0) {
        peg$fail(peg$e25);
      }
    }

    return s0;
  }

  function peg$parseJSScript() {
    var s0, s1, s2;
    s0 = peg$currPos;
    s1 = [];
    s2 = peg$parseChar();

    if (s2 === peg$FAILED) {
      s2 = peg$parseDigit();

      if (s2 === peg$FAILED) {
        s2 = peg$parseSpace();

        if (s2 === peg$FAILED) {
          s2 = peg$parseJSToken();

          if (s2 === peg$FAILED) {
            s2 = peg$parseJSString();

            if (s2 === peg$FAILED) {
              s2 = peg$parseJSScriptElementAccess();

              if (s2 === peg$FAILED) {
                s2 = peg$parseJSFnCall();
              }
            }
          }
        }
      }
    }

    if (s2 !== peg$FAILED) {
      while (s2 !== peg$FAILED) {
        s1.push(s2);
        s2 = peg$parseChar();

        if (s2 === peg$FAILED) {
          s2 = peg$parseDigit();

          if (s2 === peg$FAILED) {
            s2 = peg$parseSpace();

            if (s2 === peg$FAILED) {
              s2 = peg$parseJSToken();

              if (s2 === peg$FAILED) {
                s2 = peg$parseJSString();

                if (s2 === peg$FAILED) {
                  s2 = peg$parseJSScriptElementAccess();

                  if (s2 === peg$FAILED) {
                    s2 = peg$parseJSFnCall();
                  }
                }
              }
            }
          }
        }
      }
    } else {
      s1 = peg$FAILED;
    }

    if (s1 !== peg$FAILED) {
      s0 = input.substring(s0, peg$currPos);
    } else {
      s0 = s1;
    }

    return s0;
  }

  function peg$parseJSScriptElementAccess() {
    var s0, s1, s2, s3;
    s0 = peg$currPos;

    if (input.charCodeAt(peg$currPos) === 91) {
      s1 = peg$c1;
      peg$currPos++;
    } else {
      s1 = peg$FAILED;

      if (peg$silentFails === 0) {
        peg$fail(peg$e1);
      }
    }

    if (s1 !== peg$FAILED) {
      s2 = [];
      s3 = peg$parseDigit();

      if (s3 === peg$FAILED) {
        s3 = peg$parseChar();

        if (s3 === peg$FAILED) {
          s3 = peg$parseJSString();

          if (s3 === peg$FAILED) {
            s3 = peg$parseJSFnCall();
          }
        }
      }

      while (s3 !== peg$FAILED) {
        s2.push(s3);
        s3 = peg$parseDigit();

        if (s3 === peg$FAILED) {
          s3 = peg$parseChar();

          if (s3 === peg$FAILED) {
            s3 = peg$parseJSString();

            if (s3 === peg$FAILED) {
              s3 = peg$parseJSFnCall();
            }
          }
        }
      }

      if (input.charCodeAt(peg$currPos) === 93) {
        s3 = peg$c2;
        peg$currPos++;
      } else {
        s3 = peg$FAILED;

        if (peg$silentFails === 0) {
          peg$fail(peg$e2);
        }
      }

      if (s3 !== peg$FAILED) {
        s1 = [s1, s2, s3];
        s0 = s1;
      } else {
        peg$currPos = s0;
        s0 = peg$FAILED;
      }
    } else {
      peg$currPos = s0;
      s0 = peg$FAILED;
    }

    return s0;
  }

  function peg$parseJSString() {
    var s0, s1, s2, s3;
    s0 = peg$currPos;

    if (peg$r8.test(input.charAt(peg$currPos))) {
      s1 = input.charAt(peg$currPos);
      peg$currPos++;
    } else {
      s1 = peg$FAILED;

      if (peg$silentFails === 0) {
        peg$fail(peg$e26);
      }
    }

    if (s1 !== peg$FAILED) {
      s2 = [];

      if (peg$r3.test(input.charAt(peg$currPos))) {
        s3 = input.charAt(peg$currPos);
        peg$currPos++;
      } else {
        s3 = peg$FAILED;

        if (peg$silentFails === 0) {
          peg$fail(peg$e18);
        }
      }

      while (s3 !== peg$FAILED) {
        s2.push(s3);

        if (peg$r3.test(input.charAt(peg$currPos))) {
          s3 = input.charAt(peg$currPos);
          peg$currPos++;
        } else {
          s3 = peg$FAILED;

          if (peg$silentFails === 0) {
            peg$fail(peg$e18);
          }
        }
      }

      if (peg$r8.test(input.charAt(peg$currPos))) {
        s3 = input.charAt(peg$currPos);
        peg$currPos++;
      } else {
        s3 = peg$FAILED;

        if (peg$silentFails === 0) {
          peg$fail(peg$e26);
        }
      }

      if (s3 !== peg$FAILED) {
        s1 = [s1, s2, s3];
        s0 = s1;
      } else {
        peg$currPos = s0;
        s0 = peg$FAILED;
      }
    } else {
      peg$currPos = s0;
      s0 = peg$FAILED;
    }

    if (s0 === peg$FAILED) {
      s0 = peg$currPos;

      if (peg$r9.test(input.charAt(peg$currPos))) {
        s1 = input.charAt(peg$currPos);
        peg$currPos++;
      } else {
        s1 = peg$FAILED;

        if (peg$silentFails === 0) {
          peg$fail(peg$e27);
        }
      }

      if (s1 !== peg$FAILED) {
        s2 = [];

        if (peg$r4.test(input.charAt(peg$currPos))) {
          s3 = input.charAt(peg$currPos);
          peg$currPos++;
        } else {
          s3 = peg$FAILED;

          if (peg$silentFails === 0) {
            peg$fail(peg$e20);
          }
        }

        while (s3 !== peg$FAILED) {
          s2.push(s3);

          if (peg$r4.test(input.charAt(peg$currPos))) {
            s3 = input.charAt(peg$currPos);
            peg$currPos++;
          } else {
            s3 = peg$FAILED;

            if (peg$silentFails === 0) {
              peg$fail(peg$e20);
            }
          }
        }

        if (peg$r9.test(input.charAt(peg$currPos))) {
          s3 = input.charAt(peg$currPos);
          peg$currPos++;
        } else {
          s3 = peg$FAILED;

          if (peg$silentFails === 0) {
            peg$fail(peg$e27);
          }
        }

        if (s3 !== peg$FAILED) {
          s1 = [s1, s2, s3];
          s0 = s1;
        } else {
          peg$currPos = s0;
          s0 = peg$FAILED;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$FAILED;
      }
    }

    return s0;
  }

  function peg$parseJSToken() {
    var s0;

    if (peg$r10.test(input.charAt(peg$currPos))) {
      s0 = input.charAt(peg$currPos);
      peg$currPos++;
    } else {
      s0 = peg$FAILED;

      if (peg$silentFails === 0) {
        peg$fail(peg$e28);
      }
    }

    return s0;
  }

  function peg$parseJSFnCall() {
    var s0, s1, s2, s3;
    s0 = peg$currPos;

    if (input.charCodeAt(peg$currPos) === 40) {
      s1 = peg$c5;
      peg$currPos++;
    } else {
      s1 = peg$FAILED;

      if (peg$silentFails === 0) {
        peg$fail(peg$e5);
      }
    }

    if (s1 !== peg$FAILED) {
      s2 = [];
      s3 = peg$parseJSString();

      if (s3 === peg$FAILED) {
        s3 = peg$parseChar();

        if (s3 === peg$FAILED) {
          s3 = peg$parseDigit();

          if (s3 === peg$FAILED) {
            s3 = peg$parseJSScriptElementAccess();

            if (s3 === peg$FAILED) {
              s3 = peg$parseJSToken();

              if (s3 === peg$FAILED) {
                s3 = peg$parseSpace();

                if (s3 === peg$FAILED) {
                  s3 = peg$parseJSFnCall();
                }
              }
            }
          }
        }
      }

      while (s3 !== peg$FAILED) {
        s2.push(s3);
        s3 = peg$parseJSString();

        if (s3 === peg$FAILED) {
          s3 = peg$parseChar();

          if (s3 === peg$FAILED) {
            s3 = peg$parseDigit();

            if (s3 === peg$FAILED) {
              s3 = peg$parseJSScriptElementAccess();

              if (s3 === peg$FAILED) {
                s3 = peg$parseJSToken();

                if (s3 === peg$FAILED) {
                  s3 = peg$parseSpace();

                  if (s3 === peg$FAILED) {
                    s3 = peg$parseJSFnCall();
                  }
                }
              }
            }
          }
        }
      }

      if (input.charCodeAt(peg$currPos) === 41) {
        s3 = peg$c6;
        peg$currPos++;
      } else {
        s3 = peg$FAILED;

        if (peg$silentFails === 0) {
          peg$fail(peg$e6);
        }
      }

      if (s3 !== peg$FAILED) {
        s1 = [s1, s2, s3];
        s0 = s1;
      } else {
        peg$currPos = s0;
        s0 = peg$FAILED;
      }
    } else {
      peg$currPos = s0;
      s0 = peg$FAILED;
    }

    return s0;
  }

  function peg$parseEvalExpression() {
    var s0, s1, s2;
    s0 = peg$currPos;

    if (input.charCodeAt(peg$currPos) === 64) {
      s1 = peg$c9;
      peg$currPos++;
    } else {
      s1 = peg$FAILED;

      if (peg$silentFails === 0) {
        peg$fail(peg$e9);
      }
    }

    if (s1 !== peg$FAILED) {
      s2 = peg$parseLengthEvalExpression();

      if (s2 !== peg$FAILED) {
        peg$savedPos = s0;
        s0 = peg$f4(s2);
      } else {
        peg$currPos = s0;
        s0 = peg$FAILED;
      }
    } else {
      peg$currPos = s0;
      s0 = peg$FAILED;
    }

    return s0;
  }

  function peg$parseLengthEvalExpression() {
    var s0, s1, s2, s3, s4, s5, s6, s7;
    s0 = peg$currPos;

    if (input.substr(peg$currPos, 7) === peg$c18) {
      s1 = peg$c18;
      peg$currPos += 7;
    } else {
      s1 = peg$FAILED;

      if (peg$silentFails === 0) {
        peg$fail(peg$e29);
      }
    }

    if (s1 !== peg$FAILED) {
      s2 = [];
      s3 = peg$parseSpace();

      while (s3 !== peg$FAILED) {
        s2.push(s3);
        s3 = peg$parseSpace();
      }

      if (input.charCodeAt(peg$currPos) === 45) {
        s3 = peg$c16;
        peg$currPos++;
      } else {
        s3 = peg$FAILED;

        if (peg$silentFails === 0) {
          peg$fail(peg$e21);
        }
      }

      if (s3 !== peg$FAILED) {
        s4 = [];
        s5 = peg$parseSpace();

        while (s5 !== peg$FAILED) {
          s4.push(s5);
          s5 = peg$parseSpace();
        }

        s5 = peg$currPos;
        s6 = [];
        s7 = peg$parseDigit();

        if (s7 !== peg$FAILED) {
          while (s7 !== peg$FAILED) {
            s6.push(s7);
            s7 = peg$parseDigit();
          }
        } else {
          s6 = peg$FAILED;
        }

        if (s6 !== peg$FAILED) {
          s5 = input.substring(s5, peg$currPos);
        } else {
          s5 = s6;
        }

        if (s5 !== peg$FAILED) {
          peg$savedPos = s0;
          s0 = peg$f20(s5);
        } else {
          peg$currPos = s0;
          s0 = peg$FAILED;
        }
      } else {
        peg$currPos = s0;
        s0 = peg$FAILED;
      }
    } else {
      peg$currPos = s0;
      s0 = peg$FAILED;
    }

    return s0;
  }

  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(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));
  }
}

exports.SyntaxError = peg$SyntaxError;
exports.parse = peg$parse;
