json-p3 2.2.0 → 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /*
2
- * json-p3 version 2.2.0
2
+ * json-p3 version 2.2.2
3
3
  * https://github.com/jg-rp/json-p3
4
4
  *
5
5
  * MIT License
@@ -1241,7 +1241,7 @@ function fullMatch(pattern) {
1241
1241
  }
1242
1242
 
1243
1243
  /*
1244
- * iregexp-check version 0.1.1
1244
+ * iregexp-check version 0.1.2
1245
1245
  * https://github.com/jg-rp/js-iregexp
1246
1246
  *
1247
1247
  * MIT License
@@ -1684,7 +1684,7 @@ function peg$parse(input, options) {
1684
1684
  return s0;
1685
1685
  }
1686
1686
  function peg$parserange_quantifier() {
1687
- var s0, s1, s2, s3, s4, s5;
1687
+ var s0, s1, s2, s3, s4, s5, s6;
1688
1688
  s0 = peg$currPos;
1689
1689
  if (input.charCodeAt(peg$currPos) === 123) {
1690
1690
  s1 = peg$c1;
@@ -1696,15 +1696,32 @@ function peg$parse(input, options) {
1696
1696
  }
1697
1697
  }
1698
1698
  if (s1 !== peg$FAILED) {
1699
- s2 = input.charAt(peg$currPos);
1700
- if (peg$r1.test(s2)) {
1699
+ s2 = [];
1700
+ s3 = input.charAt(peg$currPos);
1701
+ if (peg$r1.test(s3)) {
1701
1702
  peg$currPos++;
1702
1703
  } else {
1703
- s2 = peg$FAILED;
1704
+ s3 = peg$FAILED;
1704
1705
  if (peg$silentFails === 0) {
1705
1706
  peg$fail(peg$e3);
1706
1707
  }
1707
1708
  }
1709
+ if (s3 !== peg$FAILED) {
1710
+ while (s3 !== peg$FAILED) {
1711
+ s2.push(s3);
1712
+ s3 = input.charAt(peg$currPos);
1713
+ if (peg$r1.test(s3)) {
1714
+ peg$currPos++;
1715
+ } else {
1716
+ s3 = peg$FAILED;
1717
+ if (peg$silentFails === 0) {
1718
+ peg$fail(peg$e3);
1719
+ }
1720
+ }
1721
+ }
1722
+ } else {
1723
+ s2 = peg$FAILED;
1724
+ }
1708
1725
  if (s2 !== peg$FAILED) {
1709
1726
  s3 = peg$currPos;
1710
1727
  if (input.charCodeAt(peg$currPos) === 44) {
@@ -1717,17 +1734,27 @@ function peg$parse(input, options) {
1717
1734
  }
1718
1735
  }
1719
1736
  if (s4 !== peg$FAILED) {
1720
- s5 = input.charAt(peg$currPos);
1721
- if (peg$r1.test(s5)) {
1737
+ s5 = [];
1738
+ s6 = input.charAt(peg$currPos);
1739
+ if (peg$r1.test(s6)) {
1722
1740
  peg$currPos++;
1723
1741
  } else {
1724
- s5 = peg$FAILED;
1742
+ s6 = peg$FAILED;
1725
1743
  if (peg$silentFails === 0) {
1726
1744
  peg$fail(peg$e3);
1727
1745
  }
1728
1746
  }
1729
- if (s5 === peg$FAILED) {
1730
- s5 = null;
1747
+ while (s6 !== peg$FAILED) {
1748
+ s5.push(s6);
1749
+ s6 = input.charAt(peg$currPos);
1750
+ if (peg$r1.test(s6)) {
1751
+ peg$currPos++;
1752
+ } else {
1753
+ s6 = peg$FAILED;
1754
+ if (peg$silentFails === 0) {
1755
+ peg$fail(peg$e3);
1756
+ }
1757
+ }
1731
1758
  }
1732
1759
  s4 = [s4, s5];
1733
1760
  s3 = s4;
@@ -2691,7 +2718,13 @@ class Lexer {
2691
2718
  * If the stack is empty, we are not in a function call. Remember that
2692
2719
  * function arguments can use arbitrarily nested in parentheses.
2693
2720
  */
2694
- parenStack = [];
2721
+ funcCallStack = [];
2722
+
2723
+ /**
2724
+ * A stack of parentheses and square brackets used to check for balanced
2725
+ * brackets.
2726
+ */
2727
+ bracketStack = [];
2695
2728
 
2696
2729
  /** Tokens resulting from tokenizing a JSONPath query. */
2697
2730
  tokens = [];
@@ -2820,9 +2853,19 @@ function lex(environment, path) {
2820
2853
  function tokenize(environment, path) {
2821
2854
  const [lexer, tokens] = lex(environment, path);
2822
2855
  lexer.run();
2856
+
2857
+ // If there's an error, it will be the last token with kind set to ERROR.
2823
2858
  if (tokens.length && tokens[tokens.length - 1].kind === TokenKind.ERROR) {
2824
2859
  throw new JSONPathSyntaxError(tokens[tokens.length - 1].value, tokens[tokens.length - 1]);
2825
2860
  }
2861
+
2862
+ // If the bracket stack is not empty, we hav unbalanced brackets.
2863
+ // This might not be reachable.
2864
+ if (lexer.bracketStack.length !== 0) {
2865
+ const [ch, index] = lexer.bracketStack[lexer.bracketStack.length - 1];
2866
+ const msg = "unbalanced brackets";
2867
+ throw new JSONPathSyntaxError(msg, new Token(TokenKind.ERROR, ch, index, path));
2868
+ }
2826
2869
  return tokens;
2827
2870
  }
2828
2871
  function lexRoot(l) {
@@ -2852,6 +2895,7 @@ function lexSegment(l) {
2852
2895
  }
2853
2896
  return lexDotSelector;
2854
2897
  case "[":
2898
+ l.bracketStack.push(["[", l.start]);
2855
2899
  l.emit(TokenKind.LBRACKET);
2856
2900
  return lexInsideBracketedSelection;
2857
2901
  default:
@@ -2908,6 +2952,7 @@ function lexDescendantSelection(l) {
2908
2952
  l.emit(TokenKind.WILD);
2909
2953
  return lexSegment;
2910
2954
  case "[":
2955
+ l.bracketStack.push(["[", l.start]);
2911
2956
  l.emit(TokenKind.LBRACKET);
2912
2957
  return lexInsideBracketedSelection;
2913
2958
  default:
@@ -2989,6 +3034,12 @@ function lexInsideBracketedSelection(l) {
2989
3034
  const ch = l.next();
2990
3035
  switch (ch) {
2991
3036
  case "]":
3037
+ if (l.bracketStack.length === 0 || l.bracketStack[l.bracketStack.length - 1][0] !== "[") {
3038
+ l.backup();
3039
+ l.error("unbalanced brackets");
3040
+ return null;
3041
+ }
3042
+ l.bracketStack.pop();
2992
3043
  l.emit(TokenKind.RBRACKET);
2993
3044
  return lexSegment;
2994
3045
  case "":
@@ -3030,17 +3081,13 @@ function lexInsideFilter(l) {
3030
3081
  return null;
3031
3082
  case "]":
3032
3083
  l.filterLevel -= 1;
3033
- if (l.parenStack.length === 1) {
3034
- l.error("unbalanced parentheses");
3035
- return null;
3036
- }
3037
3084
  l.backup();
3038
3085
  return lexInsideBracketedSelection;
3039
3086
  case ",":
3040
3087
  l.emit(TokenKind.COMMA);
3041
3088
  // If we have unbalanced parens, we are inside a function call and a
3042
3089
  // comma separates arguments. Otherwise a comma separates selectors.
3043
- if (l.parenStack.length) continue;
3090
+ if (l.funcCallStack.length) continue;
3044
3091
  l.filterLevel -= 1;
3045
3092
  return lexInsideBracketedSelection;
3046
3093
  case "'":
@@ -3048,18 +3095,25 @@ function lexInsideFilter(l) {
3048
3095
  case '"':
3049
3096
  return lexDoubleQuoteStringInsideFilterExpression;
3050
3097
  case "(":
3098
+ l.bracketStack.push(["(", l.start]);
3051
3099
  l.emit(TokenKind.LPAREN);
3052
3100
  // Are we in a function call? If so, a function argument contains parens.
3053
- if (l.parenStack.length) l.parenStack[l.parenStack.length - 1] += 1;
3101
+ if (l.funcCallStack.length) l.funcCallStack[l.funcCallStack.length - 1] += 1;
3054
3102
  continue;
3055
3103
  case ")":
3104
+ if (l.bracketStack.length === 0 || l.bracketStack[l.bracketStack.length - 1][0] !== "(") {
3105
+ l.backup();
3106
+ l.error("unbalanced brackets");
3107
+ return null;
3108
+ }
3109
+ l.bracketStack.pop();
3056
3110
  l.emit(TokenKind.RPAREN);
3057
3111
  // Are we closing a function call or a parenthesized expression?
3058
- if (l.parenStack.length) {
3059
- if (l.parenStack[l.parenStack.length - 1] === 1) {
3060
- l.parenStack.pop();
3112
+ if (l.funcCallStack.length) {
3113
+ if (l.funcCallStack[l.funcCallStack.length - 1] === 1) {
3114
+ l.funcCallStack.pop();
3061
3115
  } else {
3062
- l.parenStack[l.parenStack.length - 1] -= 1;
3116
+ l.funcCallStack[l.funcCallStack.length - 1] -= 1;
3063
3117
  }
3064
3118
  }
3065
3119
  continue;
@@ -3156,8 +3210,9 @@ function lexInsideFilter(l) {
3156
3210
  // functions
3157
3211
  if (l.acceptMatchRun(functionNamePattern) && l.peek() === "(") {
3158
3212
  // Keep track of parentheses for this function call.
3159
- l.parenStack.push(1);
3213
+ l.funcCallStack.push(1);
3160
3214
  l.emit(TokenKind.FUNCTION);
3215
+ l.bracketStack.push(["(", l.start]);
3161
3216
  l.next();
3162
3217
  l.ignore();
3163
3218
  continue;
@@ -5272,7 +5327,7 @@ var index = /*#__PURE__*/Object.freeze({
5272
5327
  apply: apply
5273
5328
  });
5274
5329
 
5275
- const version = "2.2.0";
5330
+ const version = "2.2.2";
5276
5331
 
5277
5332
  exports.DEFAULT_ENVIRONMENT = DEFAULT_ENVIRONMENT;
5278
5333
  exports.FunctionExpressionType = FunctionExpressionType;
@@ -1,5 +1,5 @@
1
1
  /*
2
- * json-p3 version 2.2.0
2
+ * json-p3 version 2.2.2
3
3
  * https://github.com/jg-rp/json-p3
4
4
  *
5
5
  * MIT License
@@ -1239,7 +1239,7 @@ function fullMatch(pattern) {
1239
1239
  }
1240
1240
 
1241
1241
  /*
1242
- * iregexp-check version 0.1.1
1242
+ * iregexp-check version 0.1.2
1243
1243
  * https://github.com/jg-rp/js-iregexp
1244
1244
  *
1245
1245
  * MIT License
@@ -1682,7 +1682,7 @@ function peg$parse(input, options) {
1682
1682
  return s0;
1683
1683
  }
1684
1684
  function peg$parserange_quantifier() {
1685
- var s0, s1, s2, s3, s4, s5;
1685
+ var s0, s1, s2, s3, s4, s5, s6;
1686
1686
  s0 = peg$currPos;
1687
1687
  if (input.charCodeAt(peg$currPos) === 123) {
1688
1688
  s1 = peg$c1;
@@ -1694,15 +1694,32 @@ function peg$parse(input, options) {
1694
1694
  }
1695
1695
  }
1696
1696
  if (s1 !== peg$FAILED) {
1697
- s2 = input.charAt(peg$currPos);
1698
- if (peg$r1.test(s2)) {
1697
+ s2 = [];
1698
+ s3 = input.charAt(peg$currPos);
1699
+ if (peg$r1.test(s3)) {
1699
1700
  peg$currPos++;
1700
1701
  } else {
1701
- s2 = peg$FAILED;
1702
+ s3 = peg$FAILED;
1702
1703
  if (peg$silentFails === 0) {
1703
1704
  peg$fail(peg$e3);
1704
1705
  }
1705
1706
  }
1707
+ if (s3 !== peg$FAILED) {
1708
+ while (s3 !== peg$FAILED) {
1709
+ s2.push(s3);
1710
+ s3 = input.charAt(peg$currPos);
1711
+ if (peg$r1.test(s3)) {
1712
+ peg$currPos++;
1713
+ } else {
1714
+ s3 = peg$FAILED;
1715
+ if (peg$silentFails === 0) {
1716
+ peg$fail(peg$e3);
1717
+ }
1718
+ }
1719
+ }
1720
+ } else {
1721
+ s2 = peg$FAILED;
1722
+ }
1706
1723
  if (s2 !== peg$FAILED) {
1707
1724
  s3 = peg$currPos;
1708
1725
  if (input.charCodeAt(peg$currPos) === 44) {
@@ -1715,17 +1732,27 @@ function peg$parse(input, options) {
1715
1732
  }
1716
1733
  }
1717
1734
  if (s4 !== peg$FAILED) {
1718
- s5 = input.charAt(peg$currPos);
1719
- if (peg$r1.test(s5)) {
1735
+ s5 = [];
1736
+ s6 = input.charAt(peg$currPos);
1737
+ if (peg$r1.test(s6)) {
1720
1738
  peg$currPos++;
1721
1739
  } else {
1722
- s5 = peg$FAILED;
1740
+ s6 = peg$FAILED;
1723
1741
  if (peg$silentFails === 0) {
1724
1742
  peg$fail(peg$e3);
1725
1743
  }
1726
1744
  }
1727
- if (s5 === peg$FAILED) {
1728
- s5 = null;
1745
+ while (s6 !== peg$FAILED) {
1746
+ s5.push(s6);
1747
+ s6 = input.charAt(peg$currPos);
1748
+ if (peg$r1.test(s6)) {
1749
+ peg$currPos++;
1750
+ } else {
1751
+ s6 = peg$FAILED;
1752
+ if (peg$silentFails === 0) {
1753
+ peg$fail(peg$e3);
1754
+ }
1755
+ }
1729
1756
  }
1730
1757
  s4 = [s4, s5];
1731
1758
  s3 = s4;
@@ -2689,7 +2716,13 @@ class Lexer {
2689
2716
  * If the stack is empty, we are not in a function call. Remember that
2690
2717
  * function arguments can use arbitrarily nested in parentheses.
2691
2718
  */
2692
- parenStack = [];
2719
+ funcCallStack = [];
2720
+
2721
+ /**
2722
+ * A stack of parentheses and square brackets used to check for balanced
2723
+ * brackets.
2724
+ */
2725
+ bracketStack = [];
2693
2726
 
2694
2727
  /** Tokens resulting from tokenizing a JSONPath query. */
2695
2728
  tokens = [];
@@ -2818,9 +2851,19 @@ function lex(environment, path) {
2818
2851
  function tokenize(environment, path) {
2819
2852
  const [lexer, tokens] = lex(environment, path);
2820
2853
  lexer.run();
2854
+
2855
+ // If there's an error, it will be the last token with kind set to ERROR.
2821
2856
  if (tokens.length && tokens[tokens.length - 1].kind === TokenKind.ERROR) {
2822
2857
  throw new JSONPathSyntaxError(tokens[tokens.length - 1].value, tokens[tokens.length - 1]);
2823
2858
  }
2859
+
2860
+ // If the bracket stack is not empty, we hav unbalanced brackets.
2861
+ // This might not be reachable.
2862
+ if (lexer.bracketStack.length !== 0) {
2863
+ const [ch, index] = lexer.bracketStack[lexer.bracketStack.length - 1];
2864
+ const msg = "unbalanced brackets";
2865
+ throw new JSONPathSyntaxError(msg, new Token(TokenKind.ERROR, ch, index, path));
2866
+ }
2824
2867
  return tokens;
2825
2868
  }
2826
2869
  function lexRoot(l) {
@@ -2850,6 +2893,7 @@ function lexSegment(l) {
2850
2893
  }
2851
2894
  return lexDotSelector;
2852
2895
  case "[":
2896
+ l.bracketStack.push(["[", l.start]);
2853
2897
  l.emit(TokenKind.LBRACKET);
2854
2898
  return lexInsideBracketedSelection;
2855
2899
  default:
@@ -2906,6 +2950,7 @@ function lexDescendantSelection(l) {
2906
2950
  l.emit(TokenKind.WILD);
2907
2951
  return lexSegment;
2908
2952
  case "[":
2953
+ l.bracketStack.push(["[", l.start]);
2909
2954
  l.emit(TokenKind.LBRACKET);
2910
2955
  return lexInsideBracketedSelection;
2911
2956
  default:
@@ -2987,6 +3032,12 @@ function lexInsideBracketedSelection(l) {
2987
3032
  const ch = l.next();
2988
3033
  switch (ch) {
2989
3034
  case "]":
3035
+ if (l.bracketStack.length === 0 || l.bracketStack[l.bracketStack.length - 1][0] !== "[") {
3036
+ l.backup();
3037
+ l.error("unbalanced brackets");
3038
+ return null;
3039
+ }
3040
+ l.bracketStack.pop();
2990
3041
  l.emit(TokenKind.RBRACKET);
2991
3042
  return lexSegment;
2992
3043
  case "":
@@ -3028,17 +3079,13 @@ function lexInsideFilter(l) {
3028
3079
  return null;
3029
3080
  case "]":
3030
3081
  l.filterLevel -= 1;
3031
- if (l.parenStack.length === 1) {
3032
- l.error("unbalanced parentheses");
3033
- return null;
3034
- }
3035
3082
  l.backup();
3036
3083
  return lexInsideBracketedSelection;
3037
3084
  case ",":
3038
3085
  l.emit(TokenKind.COMMA);
3039
3086
  // If we have unbalanced parens, we are inside a function call and a
3040
3087
  // comma separates arguments. Otherwise a comma separates selectors.
3041
- if (l.parenStack.length) continue;
3088
+ if (l.funcCallStack.length) continue;
3042
3089
  l.filterLevel -= 1;
3043
3090
  return lexInsideBracketedSelection;
3044
3091
  case "'":
@@ -3046,18 +3093,25 @@ function lexInsideFilter(l) {
3046
3093
  case '"':
3047
3094
  return lexDoubleQuoteStringInsideFilterExpression;
3048
3095
  case "(":
3096
+ l.bracketStack.push(["(", l.start]);
3049
3097
  l.emit(TokenKind.LPAREN);
3050
3098
  // Are we in a function call? If so, a function argument contains parens.
3051
- if (l.parenStack.length) l.parenStack[l.parenStack.length - 1] += 1;
3099
+ if (l.funcCallStack.length) l.funcCallStack[l.funcCallStack.length - 1] += 1;
3052
3100
  continue;
3053
3101
  case ")":
3102
+ if (l.bracketStack.length === 0 || l.bracketStack[l.bracketStack.length - 1][0] !== "(") {
3103
+ l.backup();
3104
+ l.error("unbalanced brackets");
3105
+ return null;
3106
+ }
3107
+ l.bracketStack.pop();
3054
3108
  l.emit(TokenKind.RPAREN);
3055
3109
  // Are we closing a function call or a parenthesized expression?
3056
- if (l.parenStack.length) {
3057
- if (l.parenStack[l.parenStack.length - 1] === 1) {
3058
- l.parenStack.pop();
3110
+ if (l.funcCallStack.length) {
3111
+ if (l.funcCallStack[l.funcCallStack.length - 1] === 1) {
3112
+ l.funcCallStack.pop();
3059
3113
  } else {
3060
- l.parenStack[l.parenStack.length - 1] -= 1;
3114
+ l.funcCallStack[l.funcCallStack.length - 1] -= 1;
3061
3115
  }
3062
3116
  }
3063
3117
  continue;
@@ -3154,8 +3208,9 @@ function lexInsideFilter(l) {
3154
3208
  // functions
3155
3209
  if (l.acceptMatchRun(functionNamePattern) && l.peek() === "(") {
3156
3210
  // Keep track of parentheses for this function call.
3157
- l.parenStack.push(1);
3211
+ l.funcCallStack.push(1);
3158
3212
  l.emit(TokenKind.FUNCTION);
3213
+ l.bracketStack.push(["(", l.start]);
3159
3214
  l.next();
3160
3215
  l.ignore();
3161
3216
  continue;
@@ -5270,6 +5325,6 @@ var index = /*#__PURE__*/Object.freeze({
5270
5325
  apply: apply
5271
5326
  });
5272
5327
 
5273
- const version = "2.2.0";
5328
+ const version = "2.2.2";
5274
5329
 
5275
5330
  export { DEFAULT_ENVIRONMENT, FunctionExpressionType, JSONPatch, JSONPatchError, JSONPatchTestFailure, JSONPathEnvironment, JSONPathError, JSONPathIndexError, JSONPathLexerError, JSONPathNode, JSONPathNodeList, JSONPathQuery, JSONPathRecursionLimitError, JSONPathSyntaxError, JSONPathTypeError, JSONPointer, Nothing, RelativeJSONPointer, Token, TokenKind, UNDEFINED, apply, compile, index as jsonpatch, index$1 as jsonpath, index$3 as jsonpointer, lazyQuery, query, resolve, version };
@@ -1,5 +1,5 @@
1
1
  /*
2
- * json-p3 version 2.2.0
2
+ * json-p3 version 2.2.2
3
3
  * https://github.com/jg-rp/json-p3
4
4
  *
5
5
  * MIT License
@@ -1242,7 +1242,7 @@ var json_p3 = (function (exports) {
1242
1242
  }
1243
1243
 
1244
1244
  /*
1245
- * iregexp-check version 0.1.1
1245
+ * iregexp-check version 0.1.2
1246
1246
  * https://github.com/jg-rp/js-iregexp
1247
1247
  *
1248
1248
  * MIT License
@@ -1685,7 +1685,7 @@ var json_p3 = (function (exports) {
1685
1685
  return s0;
1686
1686
  }
1687
1687
  function peg$parserange_quantifier() {
1688
- var s0, s1, s2, s3, s4, s5;
1688
+ var s0, s1, s2, s3, s4, s5, s6;
1689
1689
  s0 = peg$currPos;
1690
1690
  if (input.charCodeAt(peg$currPos) === 123) {
1691
1691
  s1 = peg$c1;
@@ -1697,15 +1697,32 @@ var json_p3 = (function (exports) {
1697
1697
  }
1698
1698
  }
1699
1699
  if (s1 !== peg$FAILED) {
1700
- s2 = input.charAt(peg$currPos);
1701
- if (peg$r1.test(s2)) {
1700
+ s2 = [];
1701
+ s3 = input.charAt(peg$currPos);
1702
+ if (peg$r1.test(s3)) {
1702
1703
  peg$currPos++;
1703
1704
  } else {
1704
- s2 = peg$FAILED;
1705
+ s3 = peg$FAILED;
1705
1706
  if (peg$silentFails === 0) {
1706
1707
  peg$fail(peg$e3);
1707
1708
  }
1708
1709
  }
1710
+ if (s3 !== peg$FAILED) {
1711
+ while (s3 !== peg$FAILED) {
1712
+ s2.push(s3);
1713
+ s3 = input.charAt(peg$currPos);
1714
+ if (peg$r1.test(s3)) {
1715
+ peg$currPos++;
1716
+ } else {
1717
+ s3 = peg$FAILED;
1718
+ if (peg$silentFails === 0) {
1719
+ peg$fail(peg$e3);
1720
+ }
1721
+ }
1722
+ }
1723
+ } else {
1724
+ s2 = peg$FAILED;
1725
+ }
1709
1726
  if (s2 !== peg$FAILED) {
1710
1727
  s3 = peg$currPos;
1711
1728
  if (input.charCodeAt(peg$currPos) === 44) {
@@ -1718,17 +1735,27 @@ var json_p3 = (function (exports) {
1718
1735
  }
1719
1736
  }
1720
1737
  if (s4 !== peg$FAILED) {
1721
- s5 = input.charAt(peg$currPos);
1722
- if (peg$r1.test(s5)) {
1738
+ s5 = [];
1739
+ s6 = input.charAt(peg$currPos);
1740
+ if (peg$r1.test(s6)) {
1723
1741
  peg$currPos++;
1724
1742
  } else {
1725
- s5 = peg$FAILED;
1743
+ s6 = peg$FAILED;
1726
1744
  if (peg$silentFails === 0) {
1727
1745
  peg$fail(peg$e3);
1728
1746
  }
1729
1747
  }
1730
- if (s5 === peg$FAILED) {
1731
- s5 = null;
1748
+ while (s6 !== peg$FAILED) {
1749
+ s5.push(s6);
1750
+ s6 = input.charAt(peg$currPos);
1751
+ if (peg$r1.test(s6)) {
1752
+ peg$currPos++;
1753
+ } else {
1754
+ s6 = peg$FAILED;
1755
+ if (peg$silentFails === 0) {
1756
+ peg$fail(peg$e3);
1757
+ }
1758
+ }
1732
1759
  }
1733
1760
  s4 = [s4, s5];
1734
1761
  s3 = s4;
@@ -2692,7 +2719,13 @@ var json_p3 = (function (exports) {
2692
2719
  * If the stack is empty, we are not in a function call. Remember that
2693
2720
  * function arguments can use arbitrarily nested in parentheses.
2694
2721
  */
2695
- parenStack = [];
2722
+ funcCallStack = [];
2723
+
2724
+ /**
2725
+ * A stack of parentheses and square brackets used to check for balanced
2726
+ * brackets.
2727
+ */
2728
+ bracketStack = [];
2696
2729
 
2697
2730
  /** Tokens resulting from tokenizing a JSONPath query. */
2698
2731
  tokens = [];
@@ -2821,9 +2854,19 @@ var json_p3 = (function (exports) {
2821
2854
  function tokenize(environment, path) {
2822
2855
  const [lexer, tokens] = lex(environment, path);
2823
2856
  lexer.run();
2857
+
2858
+ // If there's an error, it will be the last token with kind set to ERROR.
2824
2859
  if (tokens.length && tokens[tokens.length - 1].kind === TokenKind.ERROR) {
2825
2860
  throw new JSONPathSyntaxError(tokens[tokens.length - 1].value, tokens[tokens.length - 1]);
2826
2861
  }
2862
+
2863
+ // If the bracket stack is not empty, we hav unbalanced brackets.
2864
+ // This might not be reachable.
2865
+ if (lexer.bracketStack.length !== 0) {
2866
+ const [ch, index] = lexer.bracketStack[lexer.bracketStack.length - 1];
2867
+ const msg = "unbalanced brackets";
2868
+ throw new JSONPathSyntaxError(msg, new Token(TokenKind.ERROR, ch, index, path));
2869
+ }
2827
2870
  return tokens;
2828
2871
  }
2829
2872
  function lexRoot(l) {
@@ -2853,6 +2896,7 @@ var json_p3 = (function (exports) {
2853
2896
  }
2854
2897
  return lexDotSelector;
2855
2898
  case "[":
2899
+ l.bracketStack.push(["[", l.start]);
2856
2900
  l.emit(TokenKind.LBRACKET);
2857
2901
  return lexInsideBracketedSelection;
2858
2902
  default:
@@ -2909,6 +2953,7 @@ var json_p3 = (function (exports) {
2909
2953
  l.emit(TokenKind.WILD);
2910
2954
  return lexSegment;
2911
2955
  case "[":
2956
+ l.bracketStack.push(["[", l.start]);
2912
2957
  l.emit(TokenKind.LBRACKET);
2913
2958
  return lexInsideBracketedSelection;
2914
2959
  default:
@@ -2990,6 +3035,12 @@ var json_p3 = (function (exports) {
2990
3035
  const ch = l.next();
2991
3036
  switch (ch) {
2992
3037
  case "]":
3038
+ if (l.bracketStack.length === 0 || l.bracketStack[l.bracketStack.length - 1][0] !== "[") {
3039
+ l.backup();
3040
+ l.error("unbalanced brackets");
3041
+ return null;
3042
+ }
3043
+ l.bracketStack.pop();
2993
3044
  l.emit(TokenKind.RBRACKET);
2994
3045
  return lexSegment;
2995
3046
  case "":
@@ -3031,17 +3082,13 @@ var json_p3 = (function (exports) {
3031
3082
  return null;
3032
3083
  case "]":
3033
3084
  l.filterLevel -= 1;
3034
- if (l.parenStack.length === 1) {
3035
- l.error("unbalanced parentheses");
3036
- return null;
3037
- }
3038
3085
  l.backup();
3039
3086
  return lexInsideBracketedSelection;
3040
3087
  case ",":
3041
3088
  l.emit(TokenKind.COMMA);
3042
3089
  // If we have unbalanced parens, we are inside a function call and a
3043
3090
  // comma separates arguments. Otherwise a comma separates selectors.
3044
- if (l.parenStack.length) continue;
3091
+ if (l.funcCallStack.length) continue;
3045
3092
  l.filterLevel -= 1;
3046
3093
  return lexInsideBracketedSelection;
3047
3094
  case "'":
@@ -3049,18 +3096,25 @@ var json_p3 = (function (exports) {
3049
3096
  case '"':
3050
3097
  return lexDoubleQuoteStringInsideFilterExpression;
3051
3098
  case "(":
3099
+ l.bracketStack.push(["(", l.start]);
3052
3100
  l.emit(TokenKind.LPAREN);
3053
3101
  // Are we in a function call? If so, a function argument contains parens.
3054
- if (l.parenStack.length) l.parenStack[l.parenStack.length - 1] += 1;
3102
+ if (l.funcCallStack.length) l.funcCallStack[l.funcCallStack.length - 1] += 1;
3055
3103
  continue;
3056
3104
  case ")":
3105
+ if (l.bracketStack.length === 0 || l.bracketStack[l.bracketStack.length - 1][0] !== "(") {
3106
+ l.backup();
3107
+ l.error("unbalanced brackets");
3108
+ return null;
3109
+ }
3110
+ l.bracketStack.pop();
3057
3111
  l.emit(TokenKind.RPAREN);
3058
3112
  // Are we closing a function call or a parenthesized expression?
3059
- if (l.parenStack.length) {
3060
- if (l.parenStack[l.parenStack.length - 1] === 1) {
3061
- l.parenStack.pop();
3113
+ if (l.funcCallStack.length) {
3114
+ if (l.funcCallStack[l.funcCallStack.length - 1] === 1) {
3115
+ l.funcCallStack.pop();
3062
3116
  } else {
3063
- l.parenStack[l.parenStack.length - 1] -= 1;
3117
+ l.funcCallStack[l.funcCallStack.length - 1] -= 1;
3064
3118
  }
3065
3119
  }
3066
3120
  continue;
@@ -3157,8 +3211,9 @@ var json_p3 = (function (exports) {
3157
3211
  // functions
3158
3212
  if (l.acceptMatchRun(functionNamePattern) && l.peek() === "(") {
3159
3213
  // Keep track of parentheses for this function call.
3160
- l.parenStack.push(1);
3214
+ l.funcCallStack.push(1);
3161
3215
  l.emit(TokenKind.FUNCTION);
3216
+ l.bracketStack.push(["(", l.start]);
3162
3217
  l.next();
3163
3218
  l.ignore();
3164
3219
  continue;
@@ -5273,7 +5328,7 @@ var json_p3 = (function (exports) {
5273
5328
  apply: apply
5274
5329
  });
5275
5330
 
5276
- const version = "2.2.0";
5331
+ const version = "2.2.2";
5277
5332
 
5278
5333
  exports.DEFAULT_ENVIRONMENT = DEFAULT_ENVIRONMENT;
5279
5334
  exports.FunctionExpressionType = FunctionExpressionType;