From 1780a73145fc4d48fda1b773e310997063b32234 Mon Sep 17 00:00:00 2001 From: ArthurSonzogni Date: Sat, 27 Mar 2021 10:21:26 +0100 Subject: [PATCH] Stop using exit in parser. Using exit(EXIT_FAILURE) in the middle of a function makes kgt hard to be embedded as a library, because it interrupts the caller. The previous patch removed usage of exit for every generators: https://github.com/katef/kgt/pull/40 This one removes usage of exit for every parser. The parsing_error struct is introduced to list all the errors. Issue: - https://github.com/katef/kgt/issues/38 - https://github.com/ArthurSonzogni/Diagon/issues/19 --- src/Makefile | 2 + src/abnf/io.h | 4 +- src/abnf/parser.c | 254 ++++++++++++++++++++---------------------- src/abnf/parser.h | 4 +- src/ast.c | 1 - src/ast.h | 1 - src/bnf/io.h | 4 +- src/bnf/parser.c | 156 ++++++++++++-------------- src/bnf/parser.h | 4 +- src/iso-ebnf/io.h | 4 +- src/iso-ebnf/parser.c | 202 ++++++++++++++++----------------- src/iso-ebnf/parser.h | 4 +- src/main.c | 21 +++- src/parser.act | 97 ++++++++-------- src/parsing_error.c | 33 ++++++ src/parsing_error.h | 30 +++++ src/rbnf/io.h | 4 +- src/rbnf/parser.c | 172 ++++++++++++++-------------- src/rbnf/parser.h | 4 +- src/wsn/io.h | 4 +- src/wsn/parser.c | 196 ++++++++++++++++---------------- src/wsn/parser.h | 4 +- 22 files changed, 617 insertions(+), 588 deletions(-) create mode 100644 src/parsing_error.c create mode 100644 src/parsing_error.h diff --git a/src/Makefile b/src/Makefile index 7ac0c8a..ae3ce06 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,6 +4,7 @@ SRC += src/ast.c SRC += src/ast_binary.c SRC += src/bitmap.c SRC += src/main.c +SRC += src/parsing_error.c SRC += src/rewrite_ci.c SRC += src/rewrite_invisible.c SRC += src/txt.c @@ -22,6 +23,7 @@ ${BUILD}/bin/kgt: ${BUILD}/src/ast.o ${BUILD}/bin/kgt: ${BUILD}/src/ast_binary.o ${BUILD}/bin/kgt: ${BUILD}/src/bitmap.o ${BUILD}/bin/kgt: ${BUILD}/src/main.o +${BUILD}/bin/kgt: ${BUILD}/src/parsing_error.o ${BUILD}/bin/kgt: ${BUILD}/src/rewrite_ci.o ${BUILD}/bin/kgt: ${BUILD}/src/rewrite_invisible.o ${BUILD}/bin/kgt: ${BUILD}/src/txt.o diff --git a/src/abnf/io.h b/src/abnf/io.h index ede8bb4..508eb12 100644 --- a/src/abnf/io.h +++ b/src/abnf/io.h @@ -8,7 +8,7 @@ #define KGT_ABNF_IO_H #include "../compiler_specific.h" - +#include "../parsing_error.h" struct ast_rule; /* @@ -17,7 +17,7 @@ struct ast_rule; */ struct ast_rule * -abnf_input(int (*f)(void *opaque), void *opaque); +abnf_input(int (*f)(void *opaque), void *opaque, parsing_error_queue* errors); WARN_UNUSED_RESULT int diff --git a/src/abnf/parser.c b/src/abnf/parser.c index 7838e45..65b12c1 100644 --- a/src/abnf/parser.c +++ b/src/abnf/parser.c @@ -9,7 +9,7 @@ /* BEGINNING OF HEADER */ -#line 103 "src/parser.act" +#line 32 "src/parser.act" #include @@ -21,6 +21,7 @@ #include #include + #include "../parsing_error.h" #include "../txt.h" #include "../ast.h" #include "../xalloc.h" @@ -78,6 +79,8 @@ /* TODO: use lx's generated conveniences for the pattern buffer */ char a[512]; char *p; + + parsing_error_queue errors; }; #define CURRENT_TERMINAL (act_state->lex_tok) @@ -89,27 +92,6 @@ extern int allow_undefined; - static const char * - pattern_buffer(struct lex_state *lex_state) - { - const char *s; - - assert(lex_state != NULL); - - /* TODO */ - *lex_state->p++ = '\0'; - - s = xstrdup(lex_state->a); - if (s == NULL) { - perror("xstrdup"); - exit(EXIT_FAILURE); - } - - lex_state->p = lex_state->a; - - return s; - } - static const char * prefix(int base) { @@ -259,35 +241,55 @@ } static void - err(const struct lex_state *lex_state, const char *fmt, ...) + err(struct lex_state *lex_state, const char *fmt, ...) { - va_list ap; - assert(lex_state != NULL); + parsing_error error; + error.line = lex_state->lx.start.line; + error.column= lex_state->lx.start.col; + va_list ap; va_start(ap, fmt); - fprintf(stderr, "%u:%u: ", - lex_state->lx.start.line, lex_state->lx.start.col); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); + snprintf(error.description, PARSING_ERROR_DESCRIPTION_SIZE, fmt, ap); va_end(ap); + + parsing_error_queue_push(&(lex_state->errors), error); } static void - err_expected(const struct lex_state *lex_state, const char *token) + err_expected(struct lex_state *lex_state, const char *token) { err(lex_state, "Syntax error: expected %s", token); - exit(EXIT_FAILURE); } static void - err_unimplemented(const struct lex_state *lex_state, const char *s) + err_unimplemented(struct lex_state *lex_state, const char *s) { err(lex_state, "Unimplemented: %s", s); - exit(EXIT_FAILURE); } -#line 291 "src/abnf/parser.c" + static const char * + pattern_buffer(struct lex_state *lex_state) + { + const char *s; + + assert(lex_state != NULL); + + /* TODO */ + *lex_state->p++ = '\0'; + + s = xstrdup(lex_state->a); + if (s == NULL) { + perror("xstrdup"); + exit(EXIT_FAILURE); + } + + lex_state->p = lex_state->a; + + return s; + } + +#line 293 "src/abnf/parser.c" #ifndef ERROR_TERMINAL @@ -329,12 +331,12 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) /* BEGINNING OF EXTRACT: COUNT */ { -#line 362 "src/parser.act" +#line 363 "src/parser.act" ZI104 = strtoul(lex_state->buf.a, NULL, 10); /* TODO: range check */ -#line 338 "src/abnf/parser.c" +#line 340 "src/abnf/parser.c" } /* END OF EXTRACT: COUNT */ ADVANCE_LEXER; @@ -359,7 +361,7 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) } /* BEGINNING OF ACTION: rep-zero-or-one */ { -#line 543 "src/parser.act" +#line 544 "src/parser.act" (ZImin) = 0; (ZImax) = 1; @@ -368,7 +370,7 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) (void) (ZImin); (void) (ZImax); -#line 372 "src/abnf/parser.c" +#line 374 "src/abnf/parser.c" } /* END OF ACTION: rep-zero-or-one */ switch (CURRENT_TERMINAL) { @@ -380,23 +382,23 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-group-term */ { -#line 640 "src/parser.act" +#line 641 "src/parser.act" (ZIt) = ast_make_group_term(act_state->invisible, (ZIa)); -#line 388 "src/abnf/parser.c" +#line 390 "src/abnf/parser.c" } /* END OF ACTION: make-group-term */ /* BEGINNING OF ACTION: set-repeat */ { -#line 552 "src/parser.act" +#line 553 "src/parser.act" assert((ZImax) >= (ZImin) || !(ZImax)); (ZIt)->min = (ZImin); (ZIt)->max = (ZImax); -#line 400 "src/abnf/parser.c" +#line 402 "src/abnf/parser.c" } /* END OF ACTION: set-repeat */ } @@ -420,7 +422,7 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) /* BEGINNING OF ACTION: rep-zero-or-more */ { -#line 534 "src/parser.act" +#line 535 "src/parser.act" (ZImin) = 0; (ZI86) = 0; @@ -429,7 +431,7 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) (void) (ZImin); (void) (ZI86); -#line 433 "src/abnf/parser.c" +#line 435 "src/abnf/parser.c" } /* END OF ACTION: rep-zero-or-more */ ADVANCE_LEXER; @@ -441,14 +443,14 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) } /* BEGINNING OF ACTION: set-repeat */ { -#line 552 "src/parser.act" +#line 553 "src/parser.act" assert((ZImax) >= (ZImin) || !(ZImax)); (ZIt)->min = (ZImin); (ZIt)->max = (ZImax); -#line 452 "src/abnf/parser.c" +#line 454 "src/abnf/parser.c" } /* END OF ACTION: set-repeat */ } @@ -492,21 +494,21 @@ ZL1:; { /* BEGINNING OF ACTION: make-empty-rule */ { -#line 673 "src/parser.act" +#line 674 "src/parser.act" (ZIl) = NULL; -#line 500 "src/abnf/parser.c" +#line 502 "src/abnf/parser.c" } /* END OF ACTION: make-empty-rule */ /* BEGINNING OF ACTION: err-syntax */ { -#line 720 "src/parser.act" +#line 717 "src/parser.act" err(lex_state, "Syntax error"); exit(EXIT_FAILURE); -#line 510 "src/abnf/parser.c" +#line 512 "src/abnf/parser.c" } /* END OF ACTION: err-syntax */ } @@ -604,13 +606,13 @@ ZL2_body:; case (TOK_CHAR): /* BEGINNING OF EXTRACT: CHAR */ { -#line 341 "src/parser.act" +#line 340 "src/parser.act" assert(strlen(lex_state->buf.a) == 1); ZIc = lex_state->buf.a[0]; -#line 614 "src/abnf/parser.c" +#line 616 "src/abnf/parser.c" } /* END OF EXTRACT: CHAR */ break; @@ -628,14 +630,14 @@ ZL2_body:; /* TODO */ *lex_state->p++ = (ZIc); -#line 632 "src/abnf/parser.c" +#line 634 "src/abnf/parser.c" } /* END OF ACTION: pattern-char */ /* BEGINNING OF INLINE: body */ goto ZL2_body; /* END OF INLINE: body */ } - /*UNREACHED*/ + /* UNREACHED */ case (ERROR_TERMINAL): return; default: @@ -659,7 +661,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) /* BEGINNING OF EXTRACT: IDENT */ { -#line 354 "src/parser.act" +#line 346 "src/parser.act" /* * This rtrim() is for EBNF, which would require n-token lookahead @@ -676,13 +678,13 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) exit(EXIT_FAILURE); } -#line 680 "src/abnf/parser.c" +#line 682 "src/abnf/parser.c" } /* END OF EXTRACT: IDENT */ ADVANCE_LEXER; /* BEGINNING OF ACTION: make-rule-term */ { -#line 591 "src/parser.act" +#line 584 "src/parser.act" struct ast_rule *r; @@ -700,7 +702,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) (ZIt) = ast_make_rule_term(act_state->invisible, r); -#line 704 "src/abnf/parser.c" +#line 706 "src/abnf/parser.c" } /* END OF ACTION: make-rule-term */ } @@ -727,7 +729,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) { /* BEGINNING OF EXTRACT: BINRANGE */ { -#line 467 "src/parser.act" +#line 468 "src/parser.act" if (-1 == range(lex_state->buf.a, (unsigned char *) &ZIm, (unsigned char *) &ZIn, 2)) { if (errno == ERANGE) { @@ -739,7 +741,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) goto ZL1; } -#line 743 "src/abnf/parser.c" +#line 745 "src/abnf/parser.c" } /* END OF EXTRACT: BINRANGE */ ADVANCE_LEXER; @@ -749,7 +751,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) { /* BEGINNING OF EXTRACT: DECRANGE */ { -#line 491 "src/parser.act" +#line 492 "src/parser.act" if (-1 == range(lex_state->buf.a, (unsigned char *) &ZIm, (unsigned char *) &ZIn, 10)) { if (errno == ERANGE) { @@ -761,7 +763,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) goto ZL1; } -#line 765 "src/abnf/parser.c" +#line 767 "src/abnf/parser.c" } /* END OF EXTRACT: DECRANGE */ ADVANCE_LEXER; @@ -771,7 +773,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) { /* BEGINNING OF EXTRACT: HEXRANGE */ { -#line 503 "src/parser.act" +#line 504 "src/parser.act" if (-1 == range(lex_state->buf.a, (unsigned char *) &ZIm, (unsigned char *) &ZIn, 16)) { if (errno == ERANGE) { @@ -783,7 +785,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) goto ZL1; } -#line 787 "src/abnf/parser.c" +#line 789 "src/abnf/parser.c" } /* END OF EXTRACT: HEXRANGE */ ADVANCE_LEXER; @@ -796,7 +798,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) /* END OF INLINE: escrange */ /* BEGINNING OF ACTION: make-range-term */ { -#line 649 "src/parser.act" +#line 645 "src/parser.act" struct ast_alt *a; int i; @@ -816,7 +818,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) (ZIt) = ast_make_group_term(act_state->invisible, a); -#line 820 "src/abnf/parser.c" +#line 822 "src/abnf/parser.c" } /* END OF ACTION: make-range-term */ } @@ -832,7 +834,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) { /* BEGINNING OF EXTRACT: BINSTR */ { -#line 387 "src/parser.act" +#line 388 "src/parser.act" ZIx.p = xstrdup(lex_state->buf.a); if (ZIx.p == NULL) { @@ -852,7 +854,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) /* TODO: free */ -#line 856 "src/abnf/parser.c" +#line 858 "src/abnf/parser.c" } /* END OF EXTRACT: BINSTR */ ADVANCE_LEXER; @@ -862,7 +864,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) { /* BEGINNING OF EXTRACT: DECSTR */ { -#line 427 "src/parser.act" +#line 428 "src/parser.act" ZIx.p = xstrdup(lex_state->buf.a); if (ZIx.p == NULL) { @@ -882,7 +884,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) /* TODO: free */ -#line 886 "src/abnf/parser.c" +#line 888 "src/abnf/parser.c" } /* END OF EXTRACT: DECSTR */ ADVANCE_LEXER; @@ -892,7 +894,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) { /* BEGINNING OF EXTRACT: HEXSTR */ { -#line 447 "src/parser.act" +#line 448 "src/parser.act" ZIx.p = xstrdup(lex_state->buf.a); if (ZIx.p == NULL) { @@ -912,7 +914,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) /* TODO: free */ -#line 916 "src/abnf/parser.c" +#line 918 "src/abnf/parser.c" } /* END OF EXTRACT: HEXSTR */ ADVANCE_LEXER; @@ -925,11 +927,11 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) /* END OF INLINE: escstr */ /* BEGINNING OF ACTION: make-cs-literal-term */ { -#line 612 "src/parser.act" +#line 613 "src/parser.act" (ZIt) = ast_make_literal_term(act_state->invisible, &(ZIx), 0); -#line 933 "src/abnf/parser.c" +#line 935 "src/abnf/parser.c" } /* END OF ACTION: make-cs-literal-term */ } @@ -962,7 +964,7 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) case (TOK_IDENT): /* BEGINNING OF EXTRACT: IDENT */ { -#line 354 "src/parser.act" +#line 346 "src/parser.act" /* * This rtrim() is for EBNF, which would require n-token lookahead @@ -979,7 +981,7 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) exit(EXIT_FAILURE); } -#line 983 "src/abnf/parser.c" +#line 985 "src/abnf/parser.c" } /* END OF EXTRACT: IDENT */ break; @@ -1010,11 +1012,11 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) { /* BEGINNING OF ACTION: err-expected-equals */ { -#line 732 "src/parser.act" +#line 730 "src/parser.act" err_expected(lex_state, "production rule assignment"); -#line 1018 "src/abnf/parser.c" +#line 1020 "src/abnf/parser.c" } /* END OF ACTION: err-expected-equals */ } @@ -1028,11 +1030,11 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) } /* BEGINNING OF ACTION: make-rule */ { -#line 669 "src/parser.act" +#line 670 "src/parser.act" (ZIr) = ast_make_rule((ZIs), (ZIa)); -#line 1036 "src/abnf/parser.c" +#line 1038 "src/abnf/parser.c" } /* END OF ACTION: make-rule */ } @@ -1058,11 +1060,11 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) { /* BEGINNING OF ACTION: err-expected-equals */ { -#line 732 "src/parser.act" +#line 730 "src/parser.act" err_expected(lex_state, "production rule assignment"); -#line 1066 "src/abnf/parser.c" +#line 1068 "src/abnf/parser.c" } /* END OF ACTION: err-expected-equals */ } @@ -1071,13 +1073,13 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) /* END OF INLINE: 97 */ /* BEGINNING OF ACTION: current-rules */ { -#line 701 "src/parser.act" +#line 699 "src/parser.act" - fprintf(stderr, "unimplemented\n"); + err(lex_state, "unimplemented"); (ZIl) = NULL; goto ZL1; -#line 1081 "src/abnf/parser.c" +#line 1083 "src/abnf/parser.c" } /* END OF ACTION: current-rules */ prod_list_Hof_Halts (lex_state, act_state, &ZIa); @@ -1087,23 +1089,23 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) } /* BEGINNING OF ACTION: find-rule */ { -#line 706 "src/parser.act" +#line 705 "src/parser.act" assert((ZIs) != NULL); (ZIr) = ast_find_rule((ZIl), (ZIs)); -#line 1097 "src/abnf/parser.c" +#line 1099 "src/abnf/parser.c" } /* END OF ACTION: find-rule */ /* BEGINNING OF ACTION: add-alts */ { -#line 713 "src/parser.act" +#line 711 "src/parser.act" - fprintf(stderr, "unimplemented\n"); + err(lex_state, "Unimplemented"); goto ZL1; -#line 1107 "src/abnf/parser.c" +#line 1109 "src/abnf/parser.c" } /* END OF ACTION: add-alts */ } @@ -1134,11 +1136,11 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) { /* BEGINNING OF ACTION: err-expected-sep */ { -#line 728 "src/parser.act" +#line 726 "src/parser.act" err_expected(lex_state, "production rule separator"); -#line 1142 "src/abnf/parser.c" +#line 1144 "src/abnf/parser.c" } /* END OF ACTION: err-expected-sep */ } @@ -1164,12 +1166,12 @@ prod_87(lex_state lex_state, act_state act_state, map_count *ZOmax) { /* BEGINNING OF EXTRACT: COUNT */ { -#line 362 "src/parser.act" +#line 363 "src/parser.act" ZImax = strtoul(lex_state->buf.a, NULL, 10); /* TODO: range check */ -#line 1173 "src/abnf/parser.c" +#line 1175 "src/abnf/parser.c" } /* END OF EXTRACT: COUNT */ ADVANCE_LEXER; @@ -1181,7 +1183,7 @@ prod_87(lex_state lex_state, act_state act_state, map_count *ZOmax) /* BEGINNING OF ACTION: rep-zero-or-more */ { -#line 534 "src/parser.act" +#line 535 "src/parser.act" (ZI89) = 0; (ZImax) = 0; @@ -1190,7 +1192,7 @@ prod_87(lex_state lex_state, act_state act_state, map_count *ZOmax) (void) (ZI89); (void) (ZImax); -#line 1194 "src/abnf/parser.c" +#line 1196 "src/abnf/parser.c" } /* END OF ACTION: rep-zero-or-more */ } @@ -1216,13 +1218,11 @@ prod_101(lex_state lex_state, act_state act_state, map_rule *ZIl) } /* BEGINNING OF ACTION: add-rule-to-list */ { -#line 688 "src/parser.act" +#line 689 "src/parser.act" if (ast_find_rule((ZIr), (*ZIl)->name)) { - fprintf(stderr, "production rule <%s> already exists\n", (*ZIl)->name); - /* TODO: print location of this and previous definition */ - /* TODO: handle as warning; add rule anyway, and bail out at end */ - exit(EXIT_FAILURE); + err(lex_state, "production rule <%s> already exists", (*ZIl)->name); + return; } assert((*ZIl)->next == NULL); @@ -1270,7 +1270,7 @@ prod_102(lex_state lex_state, act_state act_state, map_term *ZIt, map_alt *ZOl) { /* BEGINNING OF ACTION: err-expected-alt */ { -#line 724 "src/parser.act" +#line 722 "src/parser.act" err_expected(lex_state, "alternative separator"); @@ -1288,7 +1288,7 @@ prod_102(lex_state lex_state, act_state act_state, map_term *ZIt, map_alt *ZOl) } /* BEGINNING OF ACTION: make-alt */ { -#line 665 "src/parser.act" +#line 666 "src/parser.act" (ZIl) = ast_make_alt(act_state->invisible, (*ZIt)); @@ -1297,7 +1297,7 @@ prod_102(lex_state lex_state, act_state act_state, map_term *ZIt, map_alt *ZOl) /* END OF ACTION: make-alt */ /* BEGINNING OF ACTION: add-alt-to-list */ { -#line 683 "src/parser.act" +#line 684 "src/parser.act" assert((ZIl)->next == NULL); (ZIl)->next = (ZIa); @@ -1311,7 +1311,7 @@ prod_102(lex_state lex_state, act_state act_state, map_term *ZIt, map_alt *ZOl) { /* BEGINNING OF ACTION: make-alt */ { -#line 665 "src/parser.act" +#line 666 "src/parser.act" (ZIl) = ast_make_alt(act_state->invisible, (*ZIt)); @@ -1349,7 +1349,7 @@ prod_103(lex_state lex_state, act_state act_state, map_term *ZIl) } /* BEGINNING OF ACTION: add-term-to-list */ { -#line 678 "src/parser.act" +#line 679 "src/parser.act" assert((*ZIl)->next == NULL); (*ZIl)->next = (ZIt); @@ -1394,7 +1394,7 @@ prod_factor_C_Celement(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-group-term */ { -#line 640 "src/parser.act" +#line 641 "src/parser.act" (ZIt) = ast_make_group_term(act_state->invisible, (ZIa)); @@ -1446,7 +1446,7 @@ prod_105(lex_state lex_state, act_state act_state, map_count *ZI104, map_term *Z } /* BEGINNING OF ACTION: set-repeat */ { -#line 552 "src/parser.act" +#line 553 "src/parser.act" assert((ZImax) >= (*ZI104) || !(ZImax)); @@ -1469,7 +1469,7 @@ prod_105(lex_state lex_state, act_state act_state, map_count *ZI104, map_term *Z } /* BEGINNING OF ACTION: set-repeat */ { -#line 552 "src/parser.act" +#line 553 "src/parser.act" assert((*ZI104) >= (*ZI104) || !(*ZI104)); @@ -1506,7 +1506,7 @@ prod_106(lex_state lex_state, act_state act_state, map_term *ZOt) /* BEGINNING OF EXTRACT: CI_LITERAL */ { -#line 372 "src/parser.act" +#line 373 "src/parser.act" ZIx.p = pattern_buffer(lex_state); ZIx.n = strlen(ZIx.p); @@ -1517,7 +1517,7 @@ prod_106(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-ci-literal-term */ { -#line 604 "src/parser.act" +#line 602 "src/parser.act" size_t i; @@ -1539,7 +1539,7 @@ prod_106(lex_state lex_state, act_state act_state, map_term *ZOt) /* BEGINNING OF EXTRACT: CS_LITERAL */ { -#line 377 "src/parser.act" +#line 378 "src/parser.act" ZIx.p = pattern_buffer(lex_state); ZIx.n = strlen(ZIx.p); @@ -1550,7 +1550,7 @@ prod_106(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-cs-literal-term */ { -#line 612 "src/parser.act" +#line 613 "src/parser.act" (ZIt) = ast_make_literal_term(act_state->invisible, &(ZIx), 0); @@ -1565,7 +1565,7 @@ prod_106(lex_state lex_state, act_state act_state, map_term *ZOt) /* BEGINNING OF EXTRACT: PROSE */ { -#line 382 "src/parser.act" +#line 383 "src/parser.act" ZIs = pattern_buffer(lex_state); @@ -1575,7 +1575,7 @@ prod_106(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-prose-term */ { -#line 622 "src/parser.act" +#line 621 "src/parser.act" const char *s; @@ -1615,7 +1615,7 @@ ZL0:; /* BEGINNING OF TRAILER */ -#line 869 "src/parser.act" +#line 738 "src/parser.act" static int @@ -1634,7 +1634,7 @@ ZL0:; } struct ast_rule * - FORM_INPUT(int (*f)(void *opaque), void *opaque) + FORM_INPUT(int (*f)(void *opaque), void *opaque, parsing_error_queue* errors) { struct act_state act_state_s; struct act_state *act_state; @@ -1658,6 +1658,7 @@ ZL0:; lex_state = &lex_state_s; lex_state->p = lex_state->a; + lex_state->errors = NULL; lx = &lex_state->lx; @@ -1678,8 +1679,8 @@ ZL0:; lx->clear = CAT(LX_PREFIX, _dynclear); lx->free = CAT(LX_PREFIX, _dynfree); - /* XXX */ - lx->free = NULL; + /* XXX */ + lx->free = NULL; /* This is a workaround for ADVANCE_LEXER assuming a pointer */ act_state = &act_state_s; @@ -1697,9 +1698,6 @@ ZL0:; const struct ast_alt *q; struct ast_term *t; struct ast_rule *r; - int ok; - - ok = 1; for (p = g; p != NULL; p = p->next) { for (q = p->alts; q != NULL; q = q->next) { @@ -1717,11 +1715,8 @@ ZL0:; } if (!allow_undefined) { - fprintf(stderr, "production rule <%s> not defined\n", t->u.rule->name); - /* TODO: print location of this and previous definition */ + err(lex_state, "production rule <%s> not defined", t->u.rule->name); /* XXX: would leak the ast_rule here */ - - ok = 0; continue; } @@ -1738,15 +1733,12 @@ ZL0:; } } } - - if (!ok) { - exit(EXIT_FAILURE); - } } + *errors = lex_state->errors; return g; } -#line 1751 "src/abnf/parser.c" +#line 1743 "src/abnf/parser.c" /* END OF FILE */ diff --git a/src/abnf/parser.h b/src/abnf/parser.h index 85aa8ee..9a58d5a 100644 --- a/src/abnf/parser.h +++ b/src/abnf/parser.h @@ -9,7 +9,7 @@ /* BEGINNING OF HEADER */ -#line 316 "src/parser.act" +#line 311 "src/parser.act" typedef struct lex_state * lex_state; @@ -24,7 +24,7 @@ extern void prod_abnf(lex_state, act_state, map_rule *); /* BEGINNING OF TRAILER */ -#line 871 "src/parser.act" +#line 861 "src/parser.act" #line 31 "src/abnf/parser.h" diff --git a/src/ast.c b/src/ast.c index 2f90512..0db84d3 100644 --- a/src/ast.c +++ b/src/ast.c @@ -239,4 +239,3 @@ ast_free_term(struct ast_term *term) /* XXX: free contents */ free(term); } - diff --git a/src/ast.h b/src/ast.h index 17861f2..474a2c8 100644 --- a/src/ast.h +++ b/src/ast.h @@ -122,4 +122,3 @@ int ast_binary(const struct ast_rule *ast); #endif - diff --git a/src/bnf/io.h b/src/bnf/io.h index 84d50b3..cd2292b 100644 --- a/src/bnf/io.h +++ b/src/bnf/io.h @@ -8,13 +8,13 @@ #define KGT_BNF_IO_H #include "../compiler_specific.h" - +#include "../parsing_error.h" struct ast_rule; #define bnf_ast_unsupported (FEATURE_AST_CI_LITERAL | FEATURE_AST_BINARY | FEATURE_AST_INVISIBLE) struct ast_rule * -bnf_input(int (*f)(void *opaque), void *opaque); +bnf_input(int (*f)(void *opaque), void *opaque, parsing_error_queue* errors); WARN_UNUSED_RESULT int diff --git a/src/bnf/parser.c b/src/bnf/parser.c index 6aa9671..170194c 100644 --- a/src/bnf/parser.c +++ b/src/bnf/parser.c @@ -9,7 +9,7 @@ /* BEGINNING OF HEADER */ -#line 103 "src/parser.act" +#line 32 "src/parser.act" #include @@ -21,6 +21,7 @@ #include #include + #include "../parsing_error.h" #include "../txt.h" #include "../ast.h" #include "../xalloc.h" @@ -78,6 +79,8 @@ /* TODO: use lx's generated conveniences for the pattern buffer */ char a[512]; char *p; + + parsing_error_queue errors; }; #define CURRENT_TERMINAL (act_state->lex_tok) @@ -89,27 +92,6 @@ extern int allow_undefined; - static const char * - pattern_buffer(struct lex_state *lex_state) - { - const char *s; - - assert(lex_state != NULL); - - /* TODO */ - *lex_state->p++ = '\0'; - - s = xstrdup(lex_state->a); - if (s == NULL) { - perror("xstrdup"); - exit(EXIT_FAILURE); - } - - lex_state->p = lex_state->a; - - return s; - } - static const char * prefix(int base) { @@ -259,35 +241,55 @@ } static void - err(const struct lex_state *lex_state, const char *fmt, ...) + err(struct lex_state *lex_state, const char *fmt, ...) { - va_list ap; - assert(lex_state != NULL); + parsing_error error; + error.line = lex_state->lx.start.line; + error.column= lex_state->lx.start.col; + va_list ap; va_start(ap, fmt); - fprintf(stderr, "%u:%u: ", - lex_state->lx.start.line, lex_state->lx.start.col); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); + snprintf(error.description, PARSING_ERROR_DESCRIPTION_SIZE, fmt, ap); va_end(ap); + + parsing_error_queue_push(&(lex_state->errors), error); } static void - err_expected(const struct lex_state *lex_state, const char *token) + err_expected(struct lex_state *lex_state, const char *token) { err(lex_state, "Syntax error: expected %s", token); - exit(EXIT_FAILURE); } static void - err_unimplemented(const struct lex_state *lex_state, const char *s) + err_unimplemented(struct lex_state *lex_state, const char *s) { err(lex_state, "Unimplemented: %s", s); - exit(EXIT_FAILURE); } -#line 291 "src/bnf/parser.c" + static const char * + pattern_buffer(struct lex_state *lex_state) + { + const char *s; + + assert(lex_state != NULL); + + /* TODO */ + *lex_state->p++ = '\0'; + + s = xstrdup(lex_state->a); + if (s == NULL) { + perror("xstrdup"); + exit(EXIT_FAILURE); + } + + lex_state->p = lex_state->a; + + return s; + } + +#line 293 "src/bnf/parser.c" #ifndef ERROR_TERMINAL @@ -427,13 +429,13 @@ ZL2_body:; case (TOK_CHAR): /* BEGINNING OF EXTRACT: CHAR */ { -#line 341 "src/parser.act" +#line 340 "src/parser.act" assert(strlen(lex_state->buf.a) == 1); ZIc = lex_state->buf.a[0]; -#line 437 "src/bnf/parser.c" +#line 439 "src/bnf/parser.c" } /* END OF EXTRACT: CHAR */ break; @@ -451,14 +453,14 @@ ZL2_body:; /* TODO */ *lex_state->p++ = (ZIc); -#line 455 "src/bnf/parser.c" +#line 457 "src/bnf/parser.c" } /* END OF ACTION: pattern-char */ /* BEGINNING OF INLINE: body */ goto ZL2_body; /* END OF INLINE: body */ } - /*UNREACHED*/ + /* UNREACHED */ case (ERROR_TERMINAL): return; default: @@ -490,21 +492,21 @@ ZL1:; { /* BEGINNING OF ACTION: make-empty-rule */ { -#line 673 "src/parser.act" +#line 674 "src/parser.act" (ZIl) = NULL; -#line 498 "src/bnf/parser.c" +#line 500 "src/bnf/parser.c" } /* END OF ACTION: make-empty-rule */ /* BEGINNING OF ACTION: err-syntax */ { -#line 720 "src/parser.act" +#line 717 "src/parser.act" err(lex_state, "Syntax error"); exit(EXIT_FAILURE); -#line 508 "src/bnf/parser.c" +#line 510 "src/bnf/parser.c" } /* END OF ACTION: err-syntax */ } @@ -523,11 +525,11 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-empty-term */ { -#line 579 "src/parser.act" +#line 580 "src/parser.act" (ZIt) = ast_make_empty_term(act_state->invisible); -#line 531 "src/bnf/parser.c" +#line 533 "src/bnf/parser.c" } /* END OF ACTION: make-empty-term */ } @@ -572,11 +574,11 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) case (TOK_NAME): /* BEGINNING OF EXTRACT: NAME */ { -#line 368 "src/parser.act" +#line 369 "src/parser.act" ZIs = pattern_buffer(lex_state); -#line 580 "src/bnf/parser.c" +#line 582 "src/bnf/parser.c" } /* END OF EXTRACT: NAME */ break; @@ -603,11 +605,11 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) { /* BEGINNING OF ACTION: err-expected-equals */ { -#line 732 "src/parser.act" +#line 730 "src/parser.act" err_expected(lex_state, "production rule assignment"); -#line 611 "src/bnf/parser.c" +#line 613 "src/bnf/parser.c" } /* END OF ACTION: err-expected-equals */ } @@ -621,11 +623,11 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) } /* BEGINNING OF ACTION: make-rule */ { -#line 669 "src/parser.act" +#line 670 "src/parser.act" (ZIr) = ast_make_rule((ZIs), (ZIa)); -#line 629 "src/bnf/parser.c" +#line 631 "src/bnf/parser.c" } /* END OF ACTION: make-rule */ /* BEGINNING OF INLINE: 83 */ @@ -649,11 +651,11 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) { /* BEGINNING OF ACTION: err-expected-sep */ { -#line 728 "src/parser.act" +#line 726 "src/parser.act" err_expected(lex_state, "production rule separator"); -#line 657 "src/bnf/parser.c" +#line 659 "src/bnf/parser.c" } /* END OF ACTION: err-expected-sep */ } @@ -684,13 +686,11 @@ prod_90(lex_state lex_state, act_state act_state, map_rule *ZIl) } /* BEGINNING OF ACTION: add-rule-to-list */ { -#line 688 "src/parser.act" +#line 689 "src/parser.act" if (ast_find_rule((ZIr), (*ZIl)->name)) { - fprintf(stderr, "production rule <%s> already exists\n", (*ZIl)->name); - /* TODO: print location of this and previous definition */ - /* TODO: handle as warning; add rule anyway, and bail out at end */ - exit(EXIT_FAILURE); + err(lex_state, "production rule <%s> already exists", (*ZIl)->name); + return; } assert((*ZIl)->next == NULL); @@ -738,7 +738,7 @@ prod_91(lex_state lex_state, act_state act_state, map_term *ZIt, map_alt *ZOl) { /* BEGINNING OF ACTION: err-expected-alt */ { -#line 724 "src/parser.act" +#line 722 "src/parser.act" err_expected(lex_state, "alternative separator"); @@ -756,7 +756,7 @@ prod_91(lex_state lex_state, act_state act_state, map_term *ZIt, map_alt *ZOl) } /* BEGINNING OF ACTION: make-alt */ { -#line 665 "src/parser.act" +#line 666 "src/parser.act" (ZIl) = ast_make_alt(act_state->invisible, (*ZIt)); @@ -765,7 +765,7 @@ prod_91(lex_state lex_state, act_state act_state, map_term *ZIt, map_alt *ZOl) /* END OF ACTION: make-alt */ /* BEGINNING OF ACTION: add-alt-to-list */ { -#line 683 "src/parser.act" +#line 684 "src/parser.act" assert((ZIl)->next == NULL); (ZIl)->next = (ZIa); @@ -779,7 +779,7 @@ prod_91(lex_state lex_state, act_state act_state, map_term *ZIt, map_alt *ZOl) { /* BEGINNING OF ACTION: make-alt */ { -#line 665 "src/parser.act" +#line 666 "src/parser.act" (ZIl) = ast_make_alt(act_state->invisible, (*ZIt)); @@ -814,7 +814,7 @@ prod_92(lex_state lex_state, act_state act_state, map_term *ZIl) } /* BEGINNING OF ACTION: add-term-to-list */ { -#line 678 "src/parser.act" +#line 679 "src/parser.act" assert((*ZIl)->next == NULL); (*ZIl)->next = (ZIt); @@ -847,7 +847,7 @@ prod_93(lex_state lex_state, act_state act_state, map_term *ZOt) /* BEGINNING OF EXTRACT: CS_LITERAL */ { -#line 377 "src/parser.act" +#line 378 "src/parser.act" ZIx.p = pattern_buffer(lex_state); ZIx.n = strlen(ZIx.p); @@ -858,7 +858,7 @@ prod_93(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-cs-literal-term */ { -#line 612 "src/parser.act" +#line 613 "src/parser.act" (ZIt) = ast_make_literal_term(act_state->invisible, &(ZIx), 0); @@ -873,7 +873,7 @@ prod_93(lex_state lex_state, act_state act_state, map_term *ZOt) /* BEGINNING OF EXTRACT: NAME */ { -#line 368 "src/parser.act" +#line 369 "src/parser.act" ZIs = pattern_buffer(lex_state); @@ -883,7 +883,7 @@ prod_93(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-rule-term */ { -#line 591 "src/parser.act" +#line 584 "src/parser.act" struct ast_rule *r; @@ -921,7 +921,7 @@ ZL0:; /* BEGINNING OF TRAILER */ -#line 869 "src/parser.act" +#line 738 "src/parser.act" static int @@ -940,7 +940,7 @@ ZL0:; } struct ast_rule * - FORM_INPUT(int (*f)(void *opaque), void *opaque) + FORM_INPUT(int (*f)(void *opaque), void *opaque, parsing_error_queue* errors) { struct act_state act_state_s; struct act_state *act_state; @@ -964,6 +964,7 @@ ZL0:; lex_state = &lex_state_s; lex_state->p = lex_state->a; + lex_state->errors = NULL; lx = &lex_state->lx; @@ -984,8 +985,8 @@ ZL0:; lx->clear = CAT(LX_PREFIX, _dynclear); lx->free = CAT(LX_PREFIX, _dynfree); - /* XXX */ - lx->free = NULL; + /* XXX */ + lx->free = NULL; /* This is a workaround for ADVANCE_LEXER assuming a pointer */ act_state = &act_state_s; @@ -1003,9 +1004,6 @@ ZL0:; const struct ast_alt *q; struct ast_term *t; struct ast_rule *r; - int ok; - - ok = 1; for (p = g; p != NULL; p = p->next) { for (q = p->alts; q != NULL; q = q->next) { @@ -1023,11 +1021,8 @@ ZL0:; } if (!allow_undefined) { - fprintf(stderr, "production rule <%s> not defined\n", t->u.rule->name); - /* TODO: print location of this and previous definition */ + err(lex_state, "production rule <%s> not defined", t->u.rule->name); /* XXX: would leak the ast_rule here */ - - ok = 0; continue; } @@ -1044,15 +1039,12 @@ ZL0:; } } } - - if (!ok) { - exit(EXIT_FAILURE); - } } + *errors = lex_state->errors; return g; } -#line 1057 "src/bnf/parser.c" +#line 1049 "src/bnf/parser.c" /* END OF FILE */ diff --git a/src/bnf/parser.h b/src/bnf/parser.h index 46fb372..27d7d7f 100644 --- a/src/bnf/parser.h +++ b/src/bnf/parser.h @@ -9,7 +9,7 @@ /* BEGINNING OF HEADER */ -#line 316 "src/parser.act" +#line 311 "src/parser.act" typedef struct lex_state * lex_state; @@ -24,7 +24,7 @@ extern void prod_bnf(lex_state, act_state, map_rule *); /* BEGINNING OF TRAILER */ -#line 871 "src/parser.act" +#line 861 "src/parser.act" #line 31 "src/bnf/parser.h" diff --git a/src/iso-ebnf/io.h b/src/iso-ebnf/io.h index b5b3218..e819866 100644 --- a/src/iso-ebnf/io.h +++ b/src/iso-ebnf/io.h @@ -8,7 +8,7 @@ #define KGT_ISO_EBNF_IO_H #include "../compiler_specific.h" - +#include "../parsing_error.h" struct ast_rule; /* @@ -19,7 +19,7 @@ struct ast_rule; #define iso_ebnf_ast_unsupported (FEATURE_AST_CI_LITERAL | FEATURE_AST_PROSE | FEATURE_AST_BINARY) struct ast_rule * -iso_ebnf_input(int (*f)(void *opaque), void *opaque); +iso_ebnf_input(int (*f)(void *opaque), void *opaque, parsing_error_queue* errors); WARN_UNUSED_RESULT int diff --git a/src/iso-ebnf/parser.c b/src/iso-ebnf/parser.c index 768786e..76bc415 100644 --- a/src/iso-ebnf/parser.c +++ b/src/iso-ebnf/parser.c @@ -9,7 +9,7 @@ /* BEGINNING OF HEADER */ -#line 103 "src/parser.act" +#line 32 "src/parser.act" #include @@ -21,6 +21,7 @@ #include #include + #include "../parsing_error.h" #include "../txt.h" #include "../ast.h" #include "../xalloc.h" @@ -78,6 +79,8 @@ /* TODO: use lx's generated conveniences for the pattern buffer */ char a[512]; char *p; + + parsing_error_queue errors; }; #define CURRENT_TERMINAL (act_state->lex_tok) @@ -89,27 +92,6 @@ extern int allow_undefined; - static const char * - pattern_buffer(struct lex_state *lex_state) - { - const char *s; - - assert(lex_state != NULL); - - /* TODO */ - *lex_state->p++ = '\0'; - - s = xstrdup(lex_state->a); - if (s == NULL) { - perror("xstrdup"); - exit(EXIT_FAILURE); - } - - lex_state->p = lex_state->a; - - return s; - } - static const char * prefix(int base) { @@ -259,35 +241,55 @@ } static void - err(const struct lex_state *lex_state, const char *fmt, ...) + err(struct lex_state *lex_state, const char *fmt, ...) { - va_list ap; - assert(lex_state != NULL); + parsing_error error; + error.line = lex_state->lx.start.line; + error.column= lex_state->lx.start.col; + va_list ap; va_start(ap, fmt); - fprintf(stderr, "%u:%u: ", - lex_state->lx.start.line, lex_state->lx.start.col); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); + snprintf(error.description, PARSING_ERROR_DESCRIPTION_SIZE, fmt, ap); va_end(ap); + + parsing_error_queue_push(&(lex_state->errors), error); } static void - err_expected(const struct lex_state *lex_state, const char *token) + err_expected(struct lex_state *lex_state, const char *token) { err(lex_state, "Syntax error: expected %s", token); - exit(EXIT_FAILURE); } static void - err_unimplemented(const struct lex_state *lex_state, const char *s) + err_unimplemented(struct lex_state *lex_state, const char *s) { err(lex_state, "Unimplemented: %s", s); - exit(EXIT_FAILURE); } -#line 291 "src/iso-ebnf/parser.c" + static const char * + pattern_buffer(struct lex_state *lex_state) + { + const char *s; + + assert(lex_state != NULL); + + /* TODO */ + *lex_state->p++ = '\0'; + + s = xstrdup(lex_state->a); + if (s == NULL) { + perror("xstrdup"); + exit(EXIT_FAILURE); + } + + lex_state->p = lex_state->a; + + return s; + } + +#line 293 "src/iso-ebnf/parser.c" #ifndef ERROR_TERMINAL @@ -341,11 +343,11 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-group-term */ { -#line 640 "src/parser.act" +#line 641 "src/parser.act" (ZIt) = ast_make_group_term(act_state->invisible, (ZIa)); -#line 349 "src/iso-ebnf/parser.c" +#line 351 "src/iso-ebnf/parser.c" } /* END OF ACTION: make-group-term */ } @@ -370,16 +372,16 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-group-term */ { -#line 640 "src/parser.act" +#line 641 "src/parser.act" (ZIt) = ast_make_group_term(act_state->invisible, (ZIa)); -#line 378 "src/iso-ebnf/parser.c" +#line 380 "src/iso-ebnf/parser.c" } /* END OF ACTION: make-group-term */ /* BEGINNING OF ACTION: rep-zero-or-one */ { -#line 543 "src/parser.act" +#line 544 "src/parser.act" (ZImin) = 0; (ZImax) = 1; @@ -388,19 +390,19 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) (void) (ZImin); (void) (ZImax); -#line 392 "src/iso-ebnf/parser.c" +#line 394 "src/iso-ebnf/parser.c" } /* END OF ACTION: rep-zero-or-one */ /* BEGINNING OF ACTION: set-repeat */ { -#line 552 "src/parser.act" +#line 553 "src/parser.act" assert((ZImax) >= (ZImin) || !(ZImax)); (ZIt)->min = (ZImin); (ZIt)->max = (ZImax); -#line 404 "src/iso-ebnf/parser.c" +#line 406 "src/iso-ebnf/parser.c" } /* END OF ACTION: set-repeat */ } @@ -425,16 +427,16 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-group-term */ { -#line 640 "src/parser.act" +#line 641 "src/parser.act" (ZIt) = ast_make_group_term(act_state->invisible, (ZIa)); -#line 433 "src/iso-ebnf/parser.c" +#line 435 "src/iso-ebnf/parser.c" } /* END OF ACTION: make-group-term */ /* BEGINNING OF ACTION: rep-zero-or-more */ { -#line 534 "src/parser.act" +#line 535 "src/parser.act" (ZImin) = 0; (ZImax) = 0; @@ -443,19 +445,19 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) (void) (ZImin); (void) (ZImax); -#line 447 "src/iso-ebnf/parser.c" +#line 449 "src/iso-ebnf/parser.c" } /* END OF ACTION: rep-zero-or-more */ /* BEGINNING OF ACTION: set-repeat */ { -#line 552 "src/parser.act" +#line 553 "src/parser.act" assert((ZImax) >= (ZImin) || !(ZImax)); (ZIt)->min = (ZImin); (ZIt)->max = (ZImax); -#line 459 "src/iso-ebnf/parser.c" +#line 461 "src/iso-ebnf/parser.c" } /* END OF ACTION: set-repeat */ } @@ -506,21 +508,21 @@ ZL1:; { /* BEGINNING OF ACTION: make-empty-rule */ { -#line 673 "src/parser.act" +#line 674 "src/parser.act" (ZIl) = NULL; -#line 514 "src/iso-ebnf/parser.c" +#line 516 "src/iso-ebnf/parser.c" } /* END OF ACTION: make-empty-rule */ /* BEGINNING OF ACTION: err-syntax */ { -#line 720 "src/parser.act" +#line 717 "src/parser.act" err(lex_state, "Syntax error"); exit(EXIT_FAILURE); -#line 524 "src/iso-ebnf/parser.c" +#line 526 "src/iso-ebnf/parser.c" } /* END OF ACTION: err-syntax */ } @@ -618,13 +620,13 @@ ZL2_body:; case (TOK_CHAR): /* BEGINNING OF EXTRACT: CHAR */ { -#line 341 "src/parser.act" +#line 340 "src/parser.act" assert(strlen(lex_state->buf.a) == 1); ZIc = lex_state->buf.a[0]; -#line 628 "src/iso-ebnf/parser.c" +#line 630 "src/iso-ebnf/parser.c" } /* END OF EXTRACT: CHAR */ break; @@ -642,14 +644,14 @@ ZL2_body:; /* TODO */ *lex_state->p++ = (ZIc); -#line 646 "src/iso-ebnf/parser.c" +#line 648 "src/iso-ebnf/parser.c" } /* END OF ACTION: pattern-char */ /* BEGINNING OF INLINE: body */ goto ZL2_body; /* END OF INLINE: body */ } - /*UNREACHED*/ + /* UNREACHED */ case (ERROR_TERMINAL): return; default: @@ -673,7 +675,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) /* BEGINNING OF EXTRACT: IDENT */ { -#line 354 "src/parser.act" +#line 346 "src/parser.act" /* * This rtrim() is for EBNF, which would require n-token lookahead @@ -690,13 +692,13 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) exit(EXIT_FAILURE); } -#line 694 "src/iso-ebnf/parser.c" +#line 696 "src/iso-ebnf/parser.c" } /* END OF EXTRACT: IDENT */ ADVANCE_LEXER; /* BEGINNING OF ACTION: make-rule-term */ { -#line 591 "src/parser.act" +#line 584 "src/parser.act" struct ast_rule *r; @@ -714,7 +716,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) (ZIt) = ast_make_rule_term(act_state->invisible, r); -#line 718 "src/iso-ebnf/parser.c" +#line 720 "src/iso-ebnf/parser.c" } /* END OF ACTION: make-rule-term */ } @@ -733,11 +735,11 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) { /* BEGINNING OF ACTION: make-empty-term */ { -#line 579 "src/parser.act" +#line 580 "src/parser.act" (ZIt) = ast_make_empty_term(act_state->invisible); -#line 741 "src/iso-ebnf/parser.c" +#line 743 "src/iso-ebnf/parser.c" } /* END OF ACTION: make-empty-term */ } @@ -769,7 +771,7 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) case (TOK_IDENT): /* BEGINNING OF EXTRACT: IDENT */ { -#line 354 "src/parser.act" +#line 346 "src/parser.act" /* * This rtrim() is for EBNF, which would require n-token lookahead @@ -786,7 +788,7 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) exit(EXIT_FAILURE); } -#line 790 "src/iso-ebnf/parser.c" +#line 792 "src/iso-ebnf/parser.c" } /* END OF EXTRACT: IDENT */ break; @@ -810,11 +812,11 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) { /* BEGINNING OF ACTION: err-expected-equals */ { -#line 732 "src/parser.act" +#line 730 "src/parser.act" err_expected(lex_state, "production rule assignment"); -#line 818 "src/iso-ebnf/parser.c" +#line 820 "src/iso-ebnf/parser.c" } /* END OF ACTION: err-expected-equals */ } @@ -828,11 +830,11 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) } /* BEGINNING OF ACTION: make-rule */ { -#line 669 "src/parser.act" +#line 670 "src/parser.act" (ZIr) = ast_make_rule((ZIs), (ZIa)); -#line 836 "src/iso-ebnf/parser.c" +#line 838 "src/iso-ebnf/parser.c" } /* END OF ACTION: make-rule */ /* BEGINNING OF INLINE: 91 */ @@ -851,11 +853,11 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) { /* BEGINNING OF ACTION: err-expected-sep */ { -#line 728 "src/parser.act" +#line 726 "src/parser.act" err_expected(lex_state, "production rule separator"); -#line 859 "src/iso-ebnf/parser.c" +#line 861 "src/iso-ebnf/parser.c" } /* END OF ACTION: err-expected-sep */ } @@ -883,12 +885,12 @@ prod_repeatable_Hfactor(lex_state lex_state, act_state act_state, map_term *ZOt) /* BEGINNING OF EXTRACT: COUNT */ { -#line 362 "src/parser.act" +#line 363 "src/parser.act" ZIn = strtoul(lex_state->buf.a, NULL, 10); /* TODO: range check */ -#line 892 "src/iso-ebnf/parser.c" +#line 894 "src/iso-ebnf/parser.c" } /* END OF EXTRACT: COUNT */ ADVANCE_LEXER; @@ -906,7 +908,7 @@ prod_repeatable_Hfactor(lex_state lex_state, act_state act_state, map_term *ZOt) } /* BEGINNING OF ACTION: mul-repeat */ { -#line 559 "src/parser.act" +#line 560 "src/parser.act" assert((ZIn) > 0); @@ -925,7 +927,7 @@ prod_repeatable_Hfactor(lex_state lex_state, act_state act_state, map_term *ZOt) (ZIt)->min *= (ZIn); (ZIt)->max *= (ZIn); -#line 929 "src/iso-ebnf/parser.c" +#line 931 "src/iso-ebnf/parser.c" } /* END OF ACTION: mul-repeat */ } @@ -965,13 +967,11 @@ prod_95(lex_state lex_state, act_state act_state, map_rule *ZIl) } /* BEGINNING OF ACTION: add-rule-to-list */ { -#line 688 "src/parser.act" +#line 689 "src/parser.act" if (ast_find_rule((ZIr), (*ZIl)->name)) { - fprintf(stderr, "production rule <%s> already exists\n", (*ZIl)->name); - /* TODO: print location of this and previous definition */ - /* TODO: handle as warning; add rule anyway, and bail out at end */ - exit(EXIT_FAILURE); + err(lex_state, "production rule <%s> already exists", (*ZIl)->name); + return; } assert((*ZIl)->next == NULL); @@ -1019,7 +1019,7 @@ prod_96(lex_state lex_state, act_state act_state, map_term *ZIt, map_alt *ZOl) { /* BEGINNING OF ACTION: err-expected-alt */ { -#line 724 "src/parser.act" +#line 722 "src/parser.act" err_expected(lex_state, "alternative separator"); @@ -1037,7 +1037,7 @@ prod_96(lex_state lex_state, act_state act_state, map_term *ZIt, map_alt *ZOl) } /* BEGINNING OF ACTION: make-alt */ { -#line 665 "src/parser.act" +#line 666 "src/parser.act" (ZIl) = ast_make_alt(act_state->invisible, (*ZIt)); @@ -1046,7 +1046,7 @@ prod_96(lex_state lex_state, act_state act_state, map_term *ZIt, map_alt *ZOl) /* END OF ACTION: make-alt */ /* BEGINNING OF ACTION: add-alt-to-list */ { -#line 683 "src/parser.act" +#line 684 "src/parser.act" assert((ZIl)->next == NULL); (ZIl)->next = (ZIa); @@ -1060,7 +1060,7 @@ prod_96(lex_state lex_state, act_state act_state, map_term *ZIt, map_alt *ZOl) { /* BEGINNING OF ACTION: make-alt */ { -#line 665 "src/parser.act" +#line 666 "src/parser.act" (ZIl) = ast_make_alt(act_state->invisible, (*ZIt)); @@ -1096,7 +1096,7 @@ prod_97(lex_state lex_state, act_state act_state) } /* BEGINNING OF ACTION: err-unimplemented-except */ { -#line 736 "src/parser.act" +#line 734 "src/parser.act" err_unimplemented(lex_state, "\"except\" productions"); @@ -1132,7 +1132,7 @@ prod_98(lex_state lex_state, act_state act_state, map_term *ZIl) } /* BEGINNING OF ACTION: add-term-to-list */ { -#line 678 "src/parser.act" +#line 679 "src/parser.act" assert((*ZIl)->next == NULL); (*ZIl)->next = (ZIt); @@ -1165,7 +1165,7 @@ prod_99(lex_state lex_state, act_state act_state, map_term *ZOt) /* BEGINNING OF EXTRACT: CS_LITERAL */ { -#line 377 "src/parser.act" +#line 378 "src/parser.act" ZIx.p = pattern_buffer(lex_state); ZIx.n = strlen(ZIx.p); @@ -1176,7 +1176,7 @@ prod_99(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-cs-literal-term */ { -#line 612 "src/parser.act" +#line 613 "src/parser.act" (ZIt) = ast_make_literal_term(act_state->invisible, &(ZIx), 0); @@ -1191,7 +1191,7 @@ prod_99(lex_state lex_state, act_state act_state, map_term *ZOt) /* BEGINNING OF EXTRACT: PROSE */ { -#line 382 "src/parser.act" +#line 383 "src/parser.act" ZIs = pattern_buffer(lex_state); @@ -1201,7 +1201,7 @@ prod_99(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-prose-term */ { -#line 622 "src/parser.act" +#line 621 "src/parser.act" const char *s; @@ -1265,7 +1265,7 @@ ZL0:; /* BEGINNING OF TRAILER */ -#line 869 "src/parser.act" +#line 738 "src/parser.act" static int @@ -1284,7 +1284,7 @@ ZL0:; } struct ast_rule * - FORM_INPUT(int (*f)(void *opaque), void *opaque) + FORM_INPUT(int (*f)(void *opaque), void *opaque, parsing_error_queue* errors) { struct act_state act_state_s; struct act_state *act_state; @@ -1308,6 +1308,7 @@ ZL0:; lex_state = &lex_state_s; lex_state->p = lex_state->a; + lex_state->errors = NULL; lx = &lex_state->lx; @@ -1328,8 +1329,8 @@ ZL0:; lx->clear = CAT(LX_PREFIX, _dynclear); lx->free = CAT(LX_PREFIX, _dynfree); - /* XXX */ - lx->free = NULL; + /* XXX */ + lx->free = NULL; /* This is a workaround for ADVANCE_LEXER assuming a pointer */ act_state = &act_state_s; @@ -1347,9 +1348,6 @@ ZL0:; const struct ast_alt *q; struct ast_term *t; struct ast_rule *r; - int ok; - - ok = 1; for (p = g; p != NULL; p = p->next) { for (q = p->alts; q != NULL; q = q->next) { @@ -1367,11 +1365,8 @@ ZL0:; } if (!allow_undefined) { - fprintf(stderr, "production rule <%s> not defined\n", t->u.rule->name); - /* TODO: print location of this and previous definition */ + err(lex_state, "production rule <%s> not defined", t->u.rule->name); /* XXX: would leak the ast_rule here */ - - ok = 0; continue; } @@ -1388,15 +1383,12 @@ ZL0:; } } } - - if (!ok) { - exit(EXIT_FAILURE); - } } + *errors = lex_state->errors; return g; } -#line 1401 "src/iso-ebnf/parser.c" +#line 1393 "src/iso-ebnf/parser.c" /* END OF FILE */ diff --git a/src/iso-ebnf/parser.h b/src/iso-ebnf/parser.h index e1d125f..da33c5a 100644 --- a/src/iso-ebnf/parser.h +++ b/src/iso-ebnf/parser.h @@ -9,7 +9,7 @@ /* BEGINNING OF HEADER */ -#line 316 "src/parser.act" +#line 311 "src/parser.act" typedef struct lex_state * lex_state; @@ -24,7 +24,7 @@ extern void prod_iso_Hebnf(lex_state, act_state, map_rule *); /* BEGINNING OF TRAILER */ -#line 871 "src/parser.act" +#line 861 "src/parser.act" #line 31 "src/iso-ebnf/parser.h" diff --git a/src/main.c b/src/main.c index 136493b..8fab373 100644 --- a/src/main.c +++ b/src/main.c @@ -16,6 +16,7 @@ #include "txt.h" #include "ast.h" +#include "parsing_error.h" #include "rewrite.h" #include "xalloc.h" #include "rrd/node.h" @@ -55,7 +56,7 @@ void __wait(int a, int b, int c, int d) { } struct io { const char *name; - struct ast_rule *(*in)(int (*f)(void *), void *); + struct ast_rule *(*in)(int (*f)(void *), void *, parsing_error_queue*); int (*out)(const struct ast_rule *); enum ast_features ast_unsupported; enum rrd_features rrd_unsupported; @@ -190,7 +191,22 @@ main(int argc, char *argv[]) assert(io->in != NULL); assert(io->out != NULL); - g = in->in(kgt_fgetc, stdin); + parsing_error_queue errors = NULL; + g = in->in(kgt_fgetc, stdin, &errors); + + int error_count = 0; + while(errors) { + error_count += 1; + parsing_error error; + parsing_error_queue_pop(&errors, &error); + + fprintf(stderr, "%u:%u: %s\n", error.line, error.column, + error.description); + } + if (error_count != 0) { + fprintf(stderr, "KGT: Exiting. %d errors reported\n", error_count); + exit(EXIT_FAILURE); + } { unsigned v; @@ -253,4 +269,3 @@ main(int argc, char *argv[]) /* TODO: free ast */ } - diff --git a/src/parser.act b/src/parser.act index 1b6e46a..b944544 100644 --- a/src/parser.act +++ b/src/parser.act @@ -40,6 +40,7 @@ #include #include + #include "../parsing_error.h" #include "../txt.h" #include "../ast.h" #include "../xalloc.h" @@ -97,6 +98,8 @@ /* TODO: use lx's generated conveniences for the pattern buffer */ char a[512]; char *p; + + parsing_error_queue errors; }; #define CURRENT_TERMINAL (act_state->lex_tok) @@ -108,27 +111,6 @@ extern int allow_undefined; - static const char * - pattern_buffer(struct lex_state *lex_state) - { - const char *s; - - assert(lex_state != NULL); - - /* TODO */ - *lex_state->p++ = '\0'; - - s = xstrdup(lex_state->a); - if (s == NULL) { - perror("xstrdup"); - exit(EXIT_FAILURE); - } - - lex_state->p = lex_state->a; - - return s; - } - static const char * prefix(int base) { @@ -278,32 +260,52 @@ } static void - err(const struct lex_state *lex_state, const char *fmt, ...) + err(struct lex_state *lex_state, const char *fmt, ...) { - va_list ap; - assert(lex_state != NULL); + parsing_error error; + error.line = lex_state->lx.start.line; + error.column= lex_state->lx.start.col; + va_list ap; va_start(ap, fmt); - fprintf(stderr, "%u:%u: ", - lex_state->lx.start.line, lex_state->lx.start.col); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); + snprintf(error.description, PARSING_ERROR_DESCRIPTION_SIZE, fmt, ap); va_end(ap); + + parsing_error_queue_push(&(lex_state->errors), error); } static void - err_expected(const struct lex_state *lex_state, const char *token) + err_expected(struct lex_state *lex_state, const char *token) { err(lex_state, "Syntax error: expected %s", token); - exit(EXIT_FAILURE); } static void - err_unimplemented(const struct lex_state *lex_state, const char *s) + err_unimplemented(struct lex_state *lex_state, const char *s) { err(lex_state, "Unimplemented: %s", s); - exit(EXIT_FAILURE); + } + + static const char * + pattern_buffer(struct lex_state *lex_state) + { + const char *s; + + assert(lex_state != NULL); + + /* TODO */ + *lex_state->p++ = '\0'; + + s = xstrdup(lex_state->a); + if (s == NULL) { + perror("xstrdup"); + exit(EXIT_FAILURE); + } + + lex_state->p = lex_state->a; + + return s; } @}, @{ @@ -686,10 +688,8 @@ : (l :ast_rule, r :ast_rule) -> () = @{ if (ast_find_rule(@l, @r->name)) { - fprintf(stderr, "production rule <%s> already exists\n", @r->name); - /* TODO: print location of this and previous definition */ - /* TODO: handle as warning; add rule anyway, and bail out at end */ - exit(EXIT_FAILURE); + err(lex_state, "production rule <%s> already exists", @r->name); + return; } assert(@r->next == NULL); @@ -697,7 +697,7 @@ @}; : () -> (l :ast_rule) = @{ - fprintf(stderr, "unimplemented\n"); + err(lex_state, "unimplemented"); @l = NULL; @!; @}; @@ -709,7 +709,7 @@ @}; : (r :ast_rule, a :ast_alt) -> () = @{ - fprintf(stderr, "unimplemented\n"); + err(lex_state, "Unimplemented"); @!; @}; @@ -753,7 +753,7 @@ } struct ast_rule * - FORM_INPUT(int (*f)(void *opaque), void *opaque) + FORM_INPUT(int (*f)(void *opaque), void *opaque, parsing_error_queue* errors) { struct act_state act_state_s; struct act_state *act_state; @@ -777,6 +777,7 @@ lex_state = &lex_state_s; lex_state->p = lex_state->a; + lex_state->errors = NULL; lx = &lex_state->lx; @@ -797,8 +798,8 @@ lx->clear = CAT(LX_PREFIX, _dynclear); lx->free = CAT(LX_PREFIX, _dynfree); - /* XXX */ - lx->free = NULL; + /* XXX */ + lx->free = NULL; /* This is a workaround for ADVANCE_LEXER assuming a pointer */ act_state = &act_state_s; @@ -816,9 +817,6 @@ const struct ast_alt *q; struct ast_term *t; struct ast_rule *r; - int ok; - - ok = 1; for (p = g; p != NULL; p = p->next) { for (q = p->alts; q != NULL; q = q->next) { @@ -836,11 +834,8 @@ } if (!allow_undefined) { - fprintf(stderr, "production rule <%s> not defined\n", t->u.rule->name); - /* TODO: print location of this and previous definition */ + err(lex_state, "production rule <%s> not defined", t->u.rule->name); /* XXX: would leak the ast_rule here */ - - ok = 0; continue; } @@ -857,16 +852,12 @@ } } } - - if (!ok) { - exit(EXIT_FAILURE); - } } + *errors = lex_state->errors; return g; } @}, @{ @}; - diff --git a/src/parsing_error.c b/src/parsing_error.c new file mode 100644 index 0000000..eda855a --- /dev/null +++ b/src/parsing_error.c @@ -0,0 +1,33 @@ +/* + * Copyright 2021 Katherine Flavel + * + * See LICENCE for the full copyright terms. + */ +#include "parsing_error.h" + +#include "xalloc.h" +#include +#include + +void parsing_error_queue_push(parsing_error_queue *queue, parsing_error error) { + // Find the end of the queue: + parsing_error_queue_element **tail = queue; + while (*tail != NULL) + tail = &((*tail)->next); + + // Allocate a parsing_error_queue and initialize it: + *tail = xmalloc(sizeof(parsing_error_queue_element)); + (*tail)->error = error; + (*tail)->next = NULL; +} + +int parsing_error_queue_pop(parsing_error_queue *queue, parsing_error *error) { + if (!*queue) + return 0; + + parsing_error_queue_element* head = *queue; + *error = head->error; + *queue = head->next; + free(head); + return 1; +} diff --git a/src/parsing_error.h b/src/parsing_error.h new file mode 100644 index 0000000..bf910a0 --- /dev/null +++ b/src/parsing_error.h @@ -0,0 +1,30 @@ +/* + * Copyright 2021 Katherine Flavel + * + * See LICENCE for the full copyright terms. + */ + +#ifndef KGT_PARSING_ERROR_H +#define KGT_PARSING_ERROR_H + +#define PARSING_ERROR_DESCRIPTION_SIZE (256) + +struct parsing_error { + int line; + int column; + char description[PARSING_ERROR_DESCRIPTION_SIZE]; +}; + +struct parsing_error_queue_element { + struct parsing_error error; + struct parsing_error_queue_element* next; +}; + +typedef struct parsing_error parsing_error; +typedef struct parsing_error_queue_element parsing_error_queue_element; +typedef parsing_error_queue_element* parsing_error_queue; + +void parsing_error_queue_push(parsing_error_queue* queue, parsing_error error); +int parsing_error_queue_pop(parsing_error_queue* queue, parsing_error* error); + +#endif // KGT_PARSING_ERROR_H diff --git a/src/rbnf/io.h b/src/rbnf/io.h index 80cef6d..028b79e 100644 --- a/src/rbnf/io.h +++ b/src/rbnf/io.h @@ -8,13 +8,13 @@ #define KGT_RBNF_IO_H #include "../compiler_specific.h" - +#include "../parsing_error.h" struct ast_rule; #define rbnf_ast_unsupported (FEATURE_AST_CI_LITERAL | FEATURE_AST_BINARY | FEATURE_AST_INVISIBLE) struct ast_rule * -rbnf_input(int (*f)(void *opaque), void *opaque); +rbnf_input(int (*f)(void *opaque), void *opaque, parsing_error_queue* errors); WARN_UNUSED_RESULT int diff --git a/src/rbnf/parser.c b/src/rbnf/parser.c index 5f7af9d..f08e33f 100644 --- a/src/rbnf/parser.c +++ b/src/rbnf/parser.c @@ -9,7 +9,7 @@ /* BEGINNING OF HEADER */ -#line 103 "src/parser.act" +#line 32 "src/parser.act" #include @@ -21,6 +21,7 @@ #include #include + #include "../parsing_error.h" #include "../txt.h" #include "../ast.h" #include "../xalloc.h" @@ -78,6 +79,8 @@ /* TODO: use lx's generated conveniences for the pattern buffer */ char a[512]; char *p; + + parsing_error_queue errors; }; #define CURRENT_TERMINAL (act_state->lex_tok) @@ -89,27 +92,6 @@ extern int allow_undefined; - static const char * - pattern_buffer(struct lex_state *lex_state) - { - const char *s; - - assert(lex_state != NULL); - - /* TODO */ - *lex_state->p++ = '\0'; - - s = xstrdup(lex_state->a); - if (s == NULL) { - perror("xstrdup"); - exit(EXIT_FAILURE); - } - - lex_state->p = lex_state->a; - - return s; - } - static const char * prefix(int base) { @@ -259,35 +241,55 @@ } static void - err(const struct lex_state *lex_state, const char *fmt, ...) + err(struct lex_state *lex_state, const char *fmt, ...) { - va_list ap; - assert(lex_state != NULL); + parsing_error error; + error.line = lex_state->lx.start.line; + error.column= lex_state->lx.start.col; + va_list ap; va_start(ap, fmt); - fprintf(stderr, "%u:%u: ", - lex_state->lx.start.line, lex_state->lx.start.col); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); + snprintf(error.description, PARSING_ERROR_DESCRIPTION_SIZE, fmt, ap); va_end(ap); + + parsing_error_queue_push(&(lex_state->errors), error); } static void - err_expected(const struct lex_state *lex_state, const char *token) + err_expected(struct lex_state *lex_state, const char *token) { err(lex_state, "Syntax error: expected %s", token); - exit(EXIT_FAILURE); } static void - err_unimplemented(const struct lex_state *lex_state, const char *s) + err_unimplemented(struct lex_state *lex_state, const char *s) { err(lex_state, "Unimplemented: %s", s); - exit(EXIT_FAILURE); } -#line 291 "src/rbnf/parser.c" + static const char * + pattern_buffer(struct lex_state *lex_state) + { + const char *s; + + assert(lex_state != NULL); + + /* TODO */ + *lex_state->p++ = '\0'; + + s = xstrdup(lex_state->a); + if (s == NULL) { + perror("xstrdup"); + exit(EXIT_FAILURE); + } + + lex_state->p = lex_state->a; + + return s; + } + +#line 293 "src/rbnf/parser.c" #ifndef ERROR_TERMINAL @@ -337,11 +339,11 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-group-term */ { -#line 640 "src/parser.act" +#line 641 "src/parser.act" (ZIt) = ast_make_group_term(act_state->invisible, (ZIa)); -#line 345 "src/rbnf/parser.c" +#line 347 "src/rbnf/parser.c" } /* END OF ACTION: make-group-term */ } @@ -362,7 +364,7 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: rep-zero-or-more */ { -#line 534 "src/parser.act" +#line 535 "src/parser.act" (ZImin) = 0; (ZImax) = 0; @@ -371,7 +373,7 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) (void) (ZImin); (void) (ZImax); -#line 375 "src/rbnf/parser.c" +#line 377 "src/rbnf/parser.c" } /* END OF ACTION: rep-zero-or-more */ } @@ -380,7 +382,7 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) { /* BEGINNING OF ACTION: rep-zero-or-one */ { -#line 543 "src/parser.act" +#line 544 "src/parser.act" (ZImin) = 0; (ZImax) = 1; @@ -389,7 +391,7 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) (void) (ZImin); (void) (ZImax); -#line 393 "src/rbnf/parser.c" +#line 395 "src/rbnf/parser.c" } /* END OF ACTION: rep-zero-or-one */ } @@ -409,23 +411,23 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-group-term */ { -#line 640 "src/parser.act" +#line 641 "src/parser.act" (ZIt) = ast_make_group_term(act_state->invisible, (ZIa)); -#line 417 "src/rbnf/parser.c" +#line 419 "src/rbnf/parser.c" } /* END OF ACTION: make-group-term */ /* BEGINNING OF ACTION: set-repeat */ { -#line 552 "src/parser.act" +#line 553 "src/parser.act" assert((ZImax) >= (ZImin) || !(ZImax)); (ZIt)->min = (ZImin); (ZIt)->max = (ZImax); -#line 429 "src/rbnf/parser.c" +#line 431 "src/rbnf/parser.c" } /* END OF ACTION: set-repeat */ } @@ -546,21 +548,21 @@ ZL1:; { /* BEGINNING OF ACTION: make-empty-rule */ { -#line 673 "src/parser.act" +#line 674 "src/parser.act" (ZIl) = NULL; -#line 554 "src/rbnf/parser.c" +#line 556 "src/rbnf/parser.c" } /* END OF ACTION: make-empty-rule */ /* BEGINNING OF ACTION: err-syntax */ { -#line 720 "src/parser.act" +#line 717 "src/parser.act" err(lex_state, "Syntax error"); exit(EXIT_FAILURE); -#line 564 "src/rbnf/parser.c" +#line 566 "src/rbnf/parser.c" } /* END OF ACTION: err-syntax */ } @@ -584,13 +586,13 @@ ZL2_body:; case (TOK_CHAR): /* BEGINNING OF EXTRACT: CHAR */ { -#line 341 "src/parser.act" +#line 340 "src/parser.act" assert(strlen(lex_state->buf.a) == 1); ZIc = lex_state->buf.a[0]; -#line 594 "src/rbnf/parser.c" +#line 596 "src/rbnf/parser.c" } /* END OF EXTRACT: CHAR */ break; @@ -608,14 +610,14 @@ ZL2_body:; /* TODO */ *lex_state->p++ = (ZIc); -#line 612 "src/rbnf/parser.c" +#line 614 "src/rbnf/parser.c" } /* END OF ACTION: pattern-char */ /* BEGINNING OF INLINE: body */ goto ZL2_body; /* END OF INLINE: body */ } - /*UNREACHED*/ + /* UNREACHED */ case (ERROR_TERMINAL): return; default: @@ -643,11 +645,11 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) case (TOK_NAME): /* BEGINNING OF EXTRACT: NAME */ { -#line 368 "src/parser.act" +#line 369 "src/parser.act" ZIs = pattern_buffer(lex_state); -#line 651 "src/rbnf/parser.c" +#line 653 "src/rbnf/parser.c" } /* END OF EXTRACT: NAME */ break; @@ -660,7 +662,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-rule-term */ { -#line 591 "src/parser.act" +#line 584 "src/parser.act" struct ast_rule *r; @@ -678,7 +680,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) (ZIt) = ast_make_rule_term(act_state->invisible, r); -#line 682 "src/rbnf/parser.c" +#line 684 "src/rbnf/parser.c" } /* END OF ACTION: make-rule-term */ } @@ -707,11 +709,11 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) case (TOK_NAME): /* BEGINNING OF EXTRACT: NAME */ { -#line 368 "src/parser.act" +#line 369 "src/parser.act" ZIs = pattern_buffer(lex_state); -#line 715 "src/rbnf/parser.c" +#line 717 "src/rbnf/parser.c" } /* END OF EXTRACT: NAME */ break; @@ -738,11 +740,11 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) { /* BEGINNING OF ACTION: err-expected-equals */ { -#line 732 "src/parser.act" +#line 730 "src/parser.act" err_expected(lex_state, "production rule assignment"); -#line 746 "src/rbnf/parser.c" +#line 748 "src/rbnf/parser.c" } /* END OF ACTION: err-expected-equals */ } @@ -756,11 +758,11 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) } /* BEGINNING OF ACTION: make-rule */ { -#line 669 "src/parser.act" +#line 670 "src/parser.act" (ZIr) = ast_make_rule((ZIs), (ZIa)); -#line 764 "src/rbnf/parser.c" +#line 766 "src/rbnf/parser.c" } /* END OF ACTION: make-rule */ /* BEGINNING OF INLINE: 85 */ @@ -784,11 +786,11 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) { /* BEGINNING OF ACTION: err-expected-sep */ { -#line 728 "src/parser.act" +#line 726 "src/parser.act" err_expected(lex_state, "production rule separator"); -#line 792 "src/rbnf/parser.c" +#line 794 "src/rbnf/parser.c" } /* END OF ACTION: err-expected-sep */ } @@ -819,13 +821,11 @@ prod_91(lex_state lex_state, act_state act_state, map_rule *ZIl) } /* BEGINNING OF ACTION: add-rule-to-list */ { -#line 688 "src/parser.act" +#line 689 "src/parser.act" if (ast_find_rule((ZIr), (*ZIl)->name)) { - fprintf(stderr, "production rule <%s> already exists\n", (*ZIl)->name); - /* TODO: print location of this and previous definition */ - /* TODO: handle as warning; add rule anyway, and bail out at end */ - exit(EXIT_FAILURE); + err(lex_state, "production rule <%s> already exists", (*ZIl)->name); + return; } assert((*ZIl)->next == NULL); @@ -873,7 +873,7 @@ prod_92(lex_state lex_state, act_state act_state, map_term *ZIt, map_alt *ZOl) { /* BEGINNING OF ACTION: err-expected-alt */ { -#line 724 "src/parser.act" +#line 722 "src/parser.act" err_expected(lex_state, "alternative separator"); @@ -891,7 +891,7 @@ prod_92(lex_state lex_state, act_state act_state, map_term *ZIt, map_alt *ZOl) } /* BEGINNING OF ACTION: make-alt */ { -#line 665 "src/parser.act" +#line 666 "src/parser.act" (ZIl) = ast_make_alt(act_state->invisible, (*ZIt)); @@ -900,7 +900,7 @@ prod_92(lex_state lex_state, act_state act_state, map_term *ZIt, map_alt *ZOl) /* END OF ACTION: make-alt */ /* BEGINNING OF ACTION: add-alt-to-list */ { -#line 683 "src/parser.act" +#line 684 "src/parser.act" assert((ZIl)->next == NULL); (ZIl)->next = (ZIa); @@ -914,7 +914,7 @@ prod_92(lex_state lex_state, act_state act_state, map_term *ZIt, map_alt *ZOl) { /* BEGINNING OF ACTION: make-alt */ { -#line 665 "src/parser.act" +#line 666 "src/parser.act" (ZIl) = ast_make_alt(act_state->invisible, (*ZIt)); @@ -949,7 +949,7 @@ prod_93(lex_state lex_state, act_state act_state, map_term *ZIl) } /* BEGINNING OF ACTION: add-term-to-list */ { -#line 678 "src/parser.act" +#line 679 "src/parser.act" assert((*ZIl)->next == NULL); (*ZIl)->next = (ZIt); @@ -972,7 +972,7 @@ ZL1:; /* BEGINNING OF TRAILER */ -#line 869 "src/parser.act" +#line 738 "src/parser.act" static int @@ -991,7 +991,7 @@ ZL1:; } struct ast_rule * - FORM_INPUT(int (*f)(void *opaque), void *opaque) + FORM_INPUT(int (*f)(void *opaque), void *opaque, parsing_error_queue* errors) { struct act_state act_state_s; struct act_state *act_state; @@ -1015,6 +1015,7 @@ ZL1:; lex_state = &lex_state_s; lex_state->p = lex_state->a; + lex_state->errors = NULL; lx = &lex_state->lx; @@ -1035,8 +1036,8 @@ ZL1:; lx->clear = CAT(LX_PREFIX, _dynclear); lx->free = CAT(LX_PREFIX, _dynfree); - /* XXX */ - lx->free = NULL; + /* XXX */ + lx->free = NULL; /* This is a workaround for ADVANCE_LEXER assuming a pointer */ act_state = &act_state_s; @@ -1054,9 +1055,6 @@ ZL1:; const struct ast_alt *q; struct ast_term *t; struct ast_rule *r; - int ok; - - ok = 1; for (p = g; p != NULL; p = p->next) { for (q = p->alts; q != NULL; q = q->next) { @@ -1074,11 +1072,8 @@ ZL1:; } if (!allow_undefined) { - fprintf(stderr, "production rule <%s> not defined\n", t->u.rule->name); - /* TODO: print location of this and previous definition */ + err(lex_state, "production rule <%s> not defined", t->u.rule->name); /* XXX: would leak the ast_rule here */ - - ok = 0; continue; } @@ -1095,15 +1090,12 @@ ZL1:; } } } - - if (!ok) { - exit(EXIT_FAILURE); - } } + *errors = lex_state->errors; return g; } -#line 1108 "src/rbnf/parser.c" +#line 1100 "src/rbnf/parser.c" /* END OF FILE */ diff --git a/src/rbnf/parser.h b/src/rbnf/parser.h index 660dfd1..6de5eb4 100644 --- a/src/rbnf/parser.h +++ b/src/rbnf/parser.h @@ -9,7 +9,7 @@ /* BEGINNING OF HEADER */ -#line 316 "src/parser.act" +#line 311 "src/parser.act" typedef struct lex_state * lex_state; @@ -24,7 +24,7 @@ extern void prod_rbnf(lex_state, act_state, map_rule *); /* BEGINNING OF TRAILER */ -#line 871 "src/parser.act" +#line 861 "src/parser.act" #line 31 "src/rbnf/parser.h" diff --git a/src/wsn/io.h b/src/wsn/io.h index f0c37c5..680e481 100644 --- a/src/wsn/io.h +++ b/src/wsn/io.h @@ -8,13 +8,13 @@ #define KGT_WSN_IO_H #include "../compiler_specific.h" - +#include "../parsing_error.h" struct ast_rule; #define wsn_ast_unsupported (FEATURE_AST_CI_LITERAL | FEATURE_AST_BINARY | FEATURE_AST_INVISIBLE) struct ast_rule * -wsn_input(int (*f)(void *opaque), void *opaque); +wsn_input(int (*f)(void *opaque), void *opaque, parsing_error_queue* errors); WARN_UNUSED_RESULT int diff --git a/src/wsn/parser.c b/src/wsn/parser.c index ded60f9..c5d5f63 100644 --- a/src/wsn/parser.c +++ b/src/wsn/parser.c @@ -9,7 +9,7 @@ /* BEGINNING OF HEADER */ -#line 103 "src/parser.act" +#line 32 "src/parser.act" #include @@ -21,6 +21,7 @@ #include #include + #include "../parsing_error.h" #include "../txt.h" #include "../ast.h" #include "../xalloc.h" @@ -78,6 +79,8 @@ /* TODO: use lx's generated conveniences for the pattern buffer */ char a[512]; char *p; + + parsing_error_queue errors; }; #define CURRENT_TERMINAL (act_state->lex_tok) @@ -89,27 +92,6 @@ extern int allow_undefined; - static const char * - pattern_buffer(struct lex_state *lex_state) - { - const char *s; - - assert(lex_state != NULL); - - /* TODO */ - *lex_state->p++ = '\0'; - - s = xstrdup(lex_state->a); - if (s == NULL) { - perror("xstrdup"); - exit(EXIT_FAILURE); - } - - lex_state->p = lex_state->a; - - return s; - } - static const char * prefix(int base) { @@ -259,35 +241,55 @@ } static void - err(const struct lex_state *lex_state, const char *fmt, ...) + err(struct lex_state *lex_state, const char *fmt, ...) { - va_list ap; - assert(lex_state != NULL); + parsing_error error; + error.line = lex_state->lx.start.line; + error.column= lex_state->lx.start.col; + va_list ap; va_start(ap, fmt); - fprintf(stderr, "%u:%u: ", - lex_state->lx.start.line, lex_state->lx.start.col); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); + snprintf(error.description, PARSING_ERROR_DESCRIPTION_SIZE, fmt, ap); va_end(ap); + + parsing_error_queue_push(&(lex_state->errors), error); } static void - err_expected(const struct lex_state *lex_state, const char *token) + err_expected(struct lex_state *lex_state, const char *token) { err(lex_state, "Syntax error: expected %s", token); - exit(EXIT_FAILURE); } static void - err_unimplemented(const struct lex_state *lex_state, const char *s) + err_unimplemented(struct lex_state *lex_state, const char *s) { err(lex_state, "Unimplemented: %s", s); - exit(EXIT_FAILURE); } -#line 291 "src/wsn/parser.c" + static const char * + pattern_buffer(struct lex_state *lex_state) + { + const char *s; + + assert(lex_state != NULL); + + /* TODO */ + *lex_state->p++ = '\0'; + + s = xstrdup(lex_state->a); + if (s == NULL) { + perror("xstrdup"); + exit(EXIT_FAILURE); + } + + lex_state->p = lex_state->a; + + return s; + } + +#line 293 "src/wsn/parser.c" #ifndef ERROR_TERMINAL @@ -337,11 +339,11 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-group-term */ { -#line 640 "src/parser.act" +#line 641 "src/parser.act" (ZIt) = ast_make_group_term(act_state->invisible, (ZIa)); -#line 345 "src/wsn/parser.c" +#line 347 "src/wsn/parser.c" } /* END OF ACTION: make-group-term */ } @@ -366,16 +368,16 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-group-term */ { -#line 640 "src/parser.act" +#line 641 "src/parser.act" (ZIt) = ast_make_group_term(act_state->invisible, (ZIa)); -#line 374 "src/wsn/parser.c" +#line 376 "src/wsn/parser.c" } /* END OF ACTION: make-group-term */ /* BEGINNING OF ACTION: rep-zero-or-one */ { -#line 543 "src/parser.act" +#line 544 "src/parser.act" (ZImin) = 0; (ZImax) = 1; @@ -384,19 +386,19 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) (void) (ZImin); (void) (ZImax); -#line 388 "src/wsn/parser.c" +#line 390 "src/wsn/parser.c" } /* END OF ACTION: rep-zero-or-one */ /* BEGINNING OF ACTION: set-repeat */ { -#line 552 "src/parser.act" +#line 553 "src/parser.act" assert((ZImax) >= (ZImin) || !(ZImax)); (ZIt)->min = (ZImin); (ZIt)->max = (ZImax); -#line 400 "src/wsn/parser.c" +#line 402 "src/wsn/parser.c" } /* END OF ACTION: set-repeat */ } @@ -421,16 +423,16 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-group-term */ { -#line 640 "src/parser.act" +#line 641 "src/parser.act" (ZIt) = ast_make_group_term(act_state->invisible, (ZIa)); -#line 429 "src/wsn/parser.c" +#line 431 "src/wsn/parser.c" } /* END OF ACTION: make-group-term */ /* BEGINNING OF ACTION: rep-zero-or-more */ { -#line 534 "src/parser.act" +#line 535 "src/parser.act" (ZImin) = 0; (ZImax) = 0; @@ -439,19 +441,19 @@ prod_factor(lex_state lex_state, act_state act_state, map_term *ZOt) (void) (ZImin); (void) (ZImax); -#line 443 "src/wsn/parser.c" +#line 445 "src/wsn/parser.c" } /* END OF ACTION: rep-zero-or-more */ /* BEGINNING OF ACTION: set-repeat */ { -#line 552 "src/parser.act" +#line 553 "src/parser.act" assert((ZImax) >= (ZImin) || !(ZImax)); (ZIt)->min = (ZImin); (ZIt)->max = (ZImax); -#line 455 "src/wsn/parser.c" +#line 457 "src/wsn/parser.c" } /* END OF ACTION: set-repeat */ } @@ -569,13 +571,13 @@ ZL2_body:; { /* BEGINNING OF EXTRACT: CHAR */ { -#line 341 "src/parser.act" +#line 340 "src/parser.act" assert(strlen(lex_state->buf.a) == 1); ZIc = lex_state->buf.a[0]; -#line 579 "src/wsn/parser.c" +#line 581 "src/wsn/parser.c" } /* END OF EXTRACT: CHAR */ ADVANCE_LEXER; @@ -585,13 +587,13 @@ ZL2_body:; { /* BEGINNING OF EXTRACT: ESC */ { -#line 335 "src/parser.act" +#line 334 "src/parser.act" assert(strlen(lex_state->buf.a) == 2); ZIc = lex_state->buf.a[0]; -#line 595 "src/wsn/parser.c" +#line 597 "src/wsn/parser.c" } /* END OF EXTRACT: ESC */ ADVANCE_LEXER; @@ -609,14 +611,14 @@ ZL2_body:; /* TODO */ *lex_state->p++ = (ZIc); -#line 613 "src/wsn/parser.c" +#line 615 "src/wsn/parser.c" } /* END OF ACTION: pattern-char */ /* BEGINNING OF INLINE: body */ goto ZL2_body; /* END OF INLINE: body */ } - /*UNREACHED*/ + /* UNREACHED */ case (ERROR_TERMINAL): return; default: @@ -639,11 +641,11 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-empty-term */ { -#line 579 "src/parser.act" +#line 580 "src/parser.act" (ZIt) = ast_make_empty_term(act_state->invisible); -#line 647 "src/wsn/parser.c" +#line 649 "src/wsn/parser.c" } /* END OF ACTION: make-empty-term */ } @@ -654,7 +656,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) /* BEGINNING OF EXTRACT: IDENT */ { -#line 354 "src/parser.act" +#line 346 "src/parser.act" /* * This rtrim() is for EBNF, which would require n-token lookahead @@ -671,13 +673,13 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) exit(EXIT_FAILURE); } -#line 675 "src/wsn/parser.c" +#line 677 "src/wsn/parser.c" } /* END OF EXTRACT: IDENT */ ADVANCE_LEXER; /* BEGINNING OF ACTION: make-rule-term */ { -#line 591 "src/parser.act" +#line 584 "src/parser.act" struct ast_rule *r; @@ -695,7 +697,7 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) (ZIt) = ast_make_rule_term(act_state->invisible, r); -#line 699 "src/wsn/parser.c" +#line 701 "src/wsn/parser.c" } /* END OF ACTION: make-rule-term */ } @@ -709,12 +711,12 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) case (TOK_CS__LITERAL): /* BEGINNING OF EXTRACT: CS_LITERAL */ { -#line 377 "src/parser.act" +#line 378 "src/parser.act" ZIx.p = pattern_buffer(lex_state); ZIx.n = strlen(ZIx.p); -#line 718 "src/wsn/parser.c" +#line 720 "src/wsn/parser.c" } /* END OF EXTRACT: CS_LITERAL */ break; @@ -727,11 +729,11 @@ prod_term(lex_state lex_state, act_state act_state, map_term *ZOt) ADVANCE_LEXER; /* BEGINNING OF ACTION: make-cs-literal-term */ { -#line 612 "src/parser.act" +#line 613 "src/parser.act" (ZIt) = ast_make_literal_term(act_state->invisible, &(ZIx), 0); -#line 735 "src/wsn/parser.c" +#line 737 "src/wsn/parser.c" } /* END OF ACTION: make-cs-literal-term */ } @@ -765,7 +767,7 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) case (TOK_IDENT): /* BEGINNING OF EXTRACT: IDENT */ { -#line 354 "src/parser.act" +#line 346 "src/parser.act" /* * This rtrim() is for EBNF, which would require n-token lookahead @@ -782,7 +784,7 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) exit(EXIT_FAILURE); } -#line 786 "src/wsn/parser.c" +#line 788 "src/wsn/parser.c" } /* END OF EXTRACT: IDENT */ break; @@ -806,11 +808,11 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) { /* BEGINNING OF ACTION: err-expected-equals */ { -#line 732 "src/parser.act" +#line 730 "src/parser.act" err_expected(lex_state, "production rule assignment"); -#line 814 "src/wsn/parser.c" +#line 816 "src/wsn/parser.c" } /* END OF ACTION: err-expected-equals */ } @@ -824,11 +826,11 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) } /* BEGINNING OF ACTION: make-rule */ { -#line 669 "src/parser.act" +#line 670 "src/parser.act" (ZIr) = ast_make_rule((ZIs), (ZIa)); -#line 832 "src/wsn/parser.c" +#line 834 "src/wsn/parser.c" } /* END OF ACTION: make-rule */ /* BEGINNING OF INLINE: 88 */ @@ -847,11 +849,11 @@ prod_rule(lex_state lex_state, act_state act_state, map_rule *ZOr) { /* BEGINNING OF ACTION: err-expected-sep */ { -#line 728 "src/parser.act" +#line 726 "src/parser.act" err_expected(lex_state, "production rule separator"); -#line 855 "src/wsn/parser.c" +#line 857 "src/wsn/parser.c" } /* END OF ACTION: err-expected-sep */ } @@ -893,21 +895,21 @@ ZL1:; { /* BEGINNING OF ACTION: make-empty-rule */ { -#line 673 "src/parser.act" +#line 674 "src/parser.act" (ZIl) = NULL; -#line 901 "src/wsn/parser.c" +#line 903 "src/wsn/parser.c" } /* END OF ACTION: make-empty-rule */ /* BEGINNING OF ACTION: err-syntax */ { -#line 720 "src/parser.act" +#line 717 "src/parser.act" err(lex_state, "Syntax error"); exit(EXIT_FAILURE); -#line 911 "src/wsn/parser.c" +#line 913 "src/wsn/parser.c" } /* END OF ACTION: err-syntax */ } @@ -930,13 +932,11 @@ prod_93(lex_state lex_state, act_state act_state, map_rule *ZIl) } /* BEGINNING OF ACTION: add-rule-to-list */ { -#line 688 "src/parser.act" +#line 689 "src/parser.act" if (ast_find_rule((ZIr), (*ZIl)->name)) { - fprintf(stderr, "production rule <%s> already exists\n", (*ZIl)->name); - /* TODO: print location of this and previous definition */ - /* TODO: handle as warning; add rule anyway, and bail out at end */ - exit(EXIT_FAILURE); + err(lex_state, "production rule <%s> already exists", (*ZIl)->name); + return; } assert((*ZIl)->next == NULL); @@ -984,7 +984,7 @@ prod_94(lex_state lex_state, act_state act_state, map_term *ZIt, map_alt *ZOl) { /* BEGINNING OF ACTION: err-expected-alt */ { -#line 724 "src/parser.act" +#line 722 "src/parser.act" err_expected(lex_state, "alternative separator"); @@ -1002,7 +1002,7 @@ prod_94(lex_state lex_state, act_state act_state, map_term *ZIt, map_alt *ZOl) } /* BEGINNING OF ACTION: make-alt */ { -#line 665 "src/parser.act" +#line 666 "src/parser.act" (ZIl) = ast_make_alt(act_state->invisible, (*ZIt)); @@ -1011,7 +1011,7 @@ prod_94(lex_state lex_state, act_state act_state, map_term *ZIt, map_alt *ZOl) /* END OF ACTION: make-alt */ /* BEGINNING OF ACTION: add-alt-to-list */ { -#line 683 "src/parser.act" +#line 684 "src/parser.act" assert((ZIl)->next == NULL); (ZIl)->next = (ZIa); @@ -1025,7 +1025,7 @@ prod_94(lex_state lex_state, act_state act_state, map_term *ZIt, map_alt *ZOl) { /* BEGINNING OF ACTION: make-alt */ { -#line 665 "src/parser.act" +#line 666 "src/parser.act" (ZIl) = ast_make_alt(act_state->invisible, (*ZIt)); @@ -1061,7 +1061,7 @@ prod_95(lex_state lex_state, act_state act_state, map_term *ZIl) } /* BEGINNING OF ACTION: add-term-to-list */ { -#line 678 "src/parser.act" +#line 679 "src/parser.act" assert((*ZIl)->next == NULL); (*ZIl)->next = (ZIt); @@ -1084,7 +1084,7 @@ ZL1:; /* BEGINNING OF TRAILER */ -#line 869 "src/parser.act" +#line 738 "src/parser.act" static int @@ -1103,7 +1103,7 @@ ZL1:; } struct ast_rule * - FORM_INPUT(int (*f)(void *opaque), void *opaque) + FORM_INPUT(int (*f)(void *opaque), void *opaque, parsing_error_queue* errors) { struct act_state act_state_s; struct act_state *act_state; @@ -1127,6 +1127,7 @@ ZL1:; lex_state = &lex_state_s; lex_state->p = lex_state->a; + lex_state->errors = NULL; lx = &lex_state->lx; @@ -1147,8 +1148,8 @@ ZL1:; lx->clear = CAT(LX_PREFIX, _dynclear); lx->free = CAT(LX_PREFIX, _dynfree); - /* XXX */ - lx->free = NULL; + /* XXX */ + lx->free = NULL; /* This is a workaround for ADVANCE_LEXER assuming a pointer */ act_state = &act_state_s; @@ -1166,9 +1167,6 @@ ZL1:; const struct ast_alt *q; struct ast_term *t; struct ast_rule *r; - int ok; - - ok = 1; for (p = g; p != NULL; p = p->next) { for (q = p->alts; q != NULL; q = q->next) { @@ -1186,11 +1184,8 @@ ZL1:; } if (!allow_undefined) { - fprintf(stderr, "production rule <%s> not defined\n", t->u.rule->name); - /* TODO: print location of this and previous definition */ + err(lex_state, "production rule <%s> not defined", t->u.rule->name); /* XXX: would leak the ast_rule here */ - - ok = 0; continue; } @@ -1207,15 +1202,12 @@ ZL1:; } } } - - if (!ok) { - exit(EXIT_FAILURE); - } } + *errors = lex_state->errors; return g; } -#line 1220 "src/wsn/parser.c" +#line 1212 "src/wsn/parser.c" /* END OF FILE */ diff --git a/src/wsn/parser.h b/src/wsn/parser.h index 8fade38..90e9bbd 100644 --- a/src/wsn/parser.h +++ b/src/wsn/parser.h @@ -9,7 +9,7 @@ /* BEGINNING OF HEADER */ -#line 316 "src/parser.act" +#line 311 "src/parser.act" typedef struct lex_state * lex_state; @@ -24,7 +24,7 @@ extern void prod_wsn(lex_state, act_state, map_rule *); /* BEGINNING OF TRAILER */ -#line 871 "src/parser.act" +#line 861 "src/parser.act" #line 31 "src/wsn/parser.h"