Skip to content

Commit 44ca1a9

Browse files
committed
Fix for line tracking over multiple statements.
Thanks to @Dcanzano for reporting this!
1 parent 5f54617 commit 44ca1a9

File tree

2 files changed

+77
-6
lines changed

2 files changed

+77
-6
lines changed

src/lib/parser.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,12 @@ int parse_each(yyrule rule, source_cb_t source, void *sourcedata,
655655
}
656656

657657
yy.position_offset = range.end;
658+
659+
offsets_clear(&(yy.line_start_offsets));
660+
if (offsets_push(&(yy.line_start_offsets), 0))
661+
{
662+
goto cleanup;
663+
}
658664
}
659665

660666
result = 0;
@@ -716,12 +722,6 @@ int parse_one(yycontext *yy, yyrule rule)
716722
goto failure;
717723
}
718724

719-
offsets_clear(&(yy->line_start_offsets));
720-
if (offsets_push(&(yy->line_start_offsets), 0))
721-
{
722-
goto failure;
723-
}
724-
725725
assert(blocks_size(&(yy->blocks)) == 1 &&
726726
"Mismatched use of `<` and `>` in grammar");
727727
assert(blocks_last(&(yy->blocks)) == top_block &&

tests/check_errors.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,76 @@ START_TEST (track_error_position_over_embedded_newline)
230230
END_TEST
231231

232232

233+
START_TEST (track_error_position_across_statements)
234+
{
235+
struct cypher_input_position last = cypher_input_position_zero;
236+
result = cypher_parse(
237+
"match (n) return n;\n"
238+
"m atch (n) return n;\n"
239+
"match (d) return d;\n"
240+
"match (bc e) return a;\n",
241+
&last, NULL, 0);
242+
ck_assert_ptr_ne(result, NULL);
243+
ck_assert_int_eq(last.offset, 84);
244+
245+
ck_assert(cypher_parse_result_fprint_ast(result, memstream, 0, NULL, 0) == 0);
246+
fflush(memstream);
247+
const char *expected = "\n"
248+
" @0 0..19 statement body=@1\n"
249+
" @1 0..19 > query clauses=[@2, @7]\n"
250+
" @2 0..10 > > MATCH pattern=@3\n"
251+
" @3 6..9 > > > pattern paths=[@4]\n"
252+
" @4 6..9 > > > > pattern path (@5)\n"
253+
" @5 6..9 > > > > > node pattern (@6)\n"
254+
" @6 7..8 > > > > > > identifier `n`\n"
255+
" @7 10..18 > > RETURN projections=[@8]\n"
256+
" @8 17..18 > > > projection expression=@9\n"
257+
" @9 17..18 > > > > identifier `n`\n"
258+
"@10 20..30 error >>m atch (n)<<\n"
259+
"@11 30..40 statement body=@12\n"
260+
"@12 31..40 > query clauses=[@13]\n"
261+
"@13 31..39 > > RETURN projections=[@14]\n"
262+
"@14 38..39 > > > projection expression=@15\n"
263+
"@15 38..39 > > > > identifier `n`\n"
264+
"@16 41..60 statement body=@17\n"
265+
"@17 41..60 > query clauses=[@18, @23]\n"
266+
"@18 41..51 > > MATCH pattern=@19\n"
267+
"@19 47..50 > > > pattern paths=[@20]\n"
268+
"@20 47..50 > > > > pattern path (@21)\n"
269+
"@21 47..50 > > > > > node pattern (@22)\n"
270+
"@22 48..49 > > > > > > identifier `d`\n"
271+
"@23 51..59 > > RETURN projections=[@24]\n"
272+
"@24 58..59 > > > projection expression=@25\n"
273+
"@25 58..59 > > > > identifier `d`\n"
274+
"@26 61..73 error >>match (bc e)<<\n"
275+
"@27 73..83 statement body=@28\n"
276+
"@28 74..83 > query clauses=[@29]\n"
277+
"@29 74..82 > > RETURN projections=[@30]\n"
278+
"@30 81..82 > > > projection expression=@31\n"
279+
"@31 81..82 > > > > identifier `a`\n";
280+
ck_assert_str_eq(memstream_buffer, expected);
281+
282+
ck_assert_int_eq(cypher_parse_result_nerrors(result), 2);
283+
284+
const cypher_parse_error_t *err = cypher_parse_result_get_error(result, 0);
285+
struct cypher_input_position pos = cypher_parse_error_position(err);
286+
ck_assert_int_eq(pos.line, 2);
287+
ck_assert_int_eq(pos.column, 2);
288+
ck_assert_int_eq(pos.offset, 21);
289+
ck_assert_str_eq(cypher_parse_error_message(err),
290+
"Invalid input ' ': expected MATCH or MERGE");
291+
292+
err = cypher_parse_result_get_error(result, 1);
293+
pos = cypher_parse_error_position(err);
294+
ck_assert_int_eq(pos.line, 4);
295+
ck_assert_int_eq(pos.column, 11);
296+
ck_assert_int_eq(pos.offset, 71);
297+
ck_assert_str_eq(cypher_parse_error_message(err),
298+
"Invalid input 'e': expected a label, '{', a parameter or ')'");
299+
}
300+
END_TEST
301+
302+
233303
TCase* errors_tcase(void)
234304
{
235305
TCase *tc = tcase_create("errors");
@@ -240,5 +310,6 @@ TCase* errors_tcase(void)
240310
tcase_add_test(tc, parse_invalid_query_and_resync);
241311
tcase_add_test(tc, parse_single_invalid_query);
242312
tcase_add_test(tc, track_error_position_over_embedded_newline);
313+
tcase_add_test(tc, track_error_position_across_statements);
243314
return tc;
244315
}

0 commit comments

Comments
 (0)