Skip to content

Commit 9dc6207

Browse files
committed
Fix bugs from latest compliance tests
1 parent 3a51a3f commit 9dc6207

File tree

3 files changed

+94
-18
lines changed

3 files changed

+94
-18
lines changed

jmespath/parser.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,13 @@ def _parse_slice_expression(self):
221221
while not current_token == 'rbracket' and index < 3:
222222
if current_token == 'colon':
223223
index += 1
224+
if index == 3:
225+
t = self._lookahead_token(0)
226+
lex_position = t['start']
227+
actual_value = t['value']
228+
actual_type = t['type']
229+
raise exceptions.ParseError(lex_position, actual_value,
230+
actual_type, 'syntax error')
224231
self._advance()
225232
elif current_token == 'number':
226233
parts[index] = self._lookahead_token(0)['value']
@@ -271,6 +278,14 @@ def _token_led_and(self, left):
271278
return ast.and_expression(left, right)
272279

273280
def _token_led_lparen(self, left):
281+
if left['type'] != 'field':
282+
# 0 - first func arg or closing paren.
283+
# -1 - '(' token
284+
# -2 - invalid function "name".
285+
prev_t = self._lookahead_token(-2)
286+
raise exceptions.ParseError(
287+
prev_t['start'], prev_t['value'], prev_t['type'],
288+
"Invalid function name '%s'" % prev_t['value'])
274289
name = left['value']
275290
args = []
276291
while not self._current_token() == 'rparen':

tests/compliance/syntax.json

Lines changed: 72 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,6 @@
1414
"expression": "foo.-11",
1515
"error": "syntax"
1616
},
17-
{
18-
"expression": "foo",
19-
"result": null
20-
},
21-
{
22-
"expression": "foo.",
23-
"error": "syntax"
24-
},
2517
{
2618
"expression": "foo.",
2719
"error": "syntax"
@@ -116,6 +108,33 @@
116108
}
117109
]
118110
},
111+
{
112+
"comment": "Paren syntax errors",
113+
"given": {},
114+
"cases": [
115+
{
116+
"comment": "missing closing paren",
117+
"expression": "(@",
118+
"error": "syntax"
119+
}
120+
]
121+
},
122+
{
123+
"comment": "Function syntax errors",
124+
"given": {},
125+
"cases": [
126+
{
127+
"comment": "invalid start of function",
128+
"expression": "@(foo)",
129+
"error": "syntax"
130+
},
131+
{
132+
"comment": "function names cannot be quoted",
133+
"expression": "\"foo\"(bar)",
134+
"error": "syntax"
135+
}
136+
]
137+
},
119138
{
120139
"comment": "Wildcard syntax",
121140
"given": {"type": "object"},
@@ -199,6 +218,37 @@
199218
{
200219
"expression": "foo[#]",
201220
"error": "syntax"
221+
},
222+
{
223+
"comment": "missing rbracket for led wildcard index",
224+
"expression": "led[*",
225+
"error": "syntax"
226+
}
227+
]
228+
},
229+
{
230+
"comment": "slice syntax",
231+
"given": {},
232+
"cases": [
233+
{
234+
"comment": "slice expected colon or rbracket",
235+
"expression": "[:@]",
236+
"error": "syntax"
237+
},
238+
{
239+
"comment": "slice has too many colons",
240+
"expression": "[:::]",
241+
"error": "syntax"
242+
},
243+
{
244+
"comment": "slice expected number",
245+
"expression": "[:@:]",
246+
"error": "syntax"
247+
},
248+
{
249+
"comment": "slice expected number of colon",
250+
"expression": "[:1@]",
251+
"error": "syntax"
202252
}
203253
]
204254
},
@@ -358,16 +408,6 @@
358408
"expression": "a.{foo}",
359409
"error": "syntax"
360410
},
361-
{
362-
"comment": "Missing value",
363-
"expression": "a.{foo:}",
364-
"error": "syntax"
365-
},
366-
{
367-
"comment": "Missing value with trailing comma",
368-
"expression": "a.{foo: ,}",
369-
"error": "syntax"
370-
},
371411
{
372412
"comment": "Valid multi-select hash extraction",
373413
"expression": "a.{foo: bar}",
@@ -402,6 +442,11 @@
402442
"comment": "Nested multi select",
403443
"expression": "{\"\\\\\":{\" \":*}}",
404444
"result": {"\\": {" ": ["object"]}}
445+
},
446+
{
447+
"comment": "Missing closing } after a valid nud",
448+
"expression": "{a: @",
449+
"error": "syntax"
405450
}
406451
]
407452
},
@@ -574,6 +619,11 @@
574619
"comment": "Two level flattened projection of a literal",
575620
"expression": "twolen[].threelen[].`\"bar\"`",
576621
"error": "syntax"
622+
},
623+
{
624+
"comment": "expects closing ]",
625+
"expression": "foo[? @ | @",
626+
"error": "syntax"
577627
}
578628
]
579629
},
@@ -592,6 +642,10 @@
592642
{
593643
"expression": "\"\\\\\"",
594644
"result": null
645+
},
646+
{
647+
"expression": "\"\\u\"",
648+
"error": "syntax"
595649
}
596650
]
597651
},

tests/test_compliance.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,13 @@ def _test_error_expression(given, expression, error, filename):
9494
except ValueError:
9595
# Test passes, it raised a parse error as expected.
9696
pass
97+
except Exception as e:
98+
# Failure because an unexpected exception was raised.
99+
error_msg = ("\n\n (%s) The expression '%s' was suppose to be a "
100+
"syntax error, but it raised an unexpected error:\n\n%s" % (
101+
filename, expression, e))
102+
error_msg = error_msg.replace(r'\n', '\n')
103+
raise AssertionError(error_msg)
97104
else:
98105
error_msg = ("\n\n (%s) The expression '%s' was suppose to be a "
99106
"syntax error, but it successfully parsed as:\n\n%s" % (

0 commit comments

Comments
 (0)