From b7ee5df3559aee4e01eaae104f8e8e825f135d97 Mon Sep 17 00:00:00 2001 From: steve-chavez Date: Sun, 20 Aug 2023 17:28:52 -0500 Subject: [PATCH 1/2] refactor: rename grow_results to mpc_grow_results To not cause naming conflicts as mentioned on https://github.com/orangeduck/mpc/pull/166#issuecomment-1685146508 --- mpc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mpc.c b/mpc.c index a3d6c7b..c2b0389 100644 --- a/mpc.c +++ b/mpc.c @@ -1046,7 +1046,7 @@ enum { #define MPC_MAX_RECURSION_DEPTH 1000 -static mpc_result_t *grow_results(mpc_input_t *i, int j, mpc_result_t *results_stk, mpc_result_t *results){ +static mpc_result_t *mpc_grow_results(mpc_input_t *i, int j, mpc_result_t *results_stk, mpc_result_t *results){ mpc_result_t *tmp_results = results; if (j == MPC_PARSE_STACK_MIN) { @@ -1190,7 +1190,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e while (mpc_parse_run(i, p->data.repeat.x, &results[j], e, depth+1)) { j++; - results = grow_results(i, j, results_stk, results); + results = mpc_grow_results(i, j, results_stk, results); } *e = mpc_err_merge(i, *e, results[j].error); @@ -1205,7 +1205,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e while (mpc_parse_run(i, p->data.repeat.x, &results[j], e, depth+1)) { j++; - results = grow_results(i, j, results_stk, results); + results = mpc_grow_results(i, j, results_stk, results); } if (j == 0) { From b866236aad8226e02fcd71e44d6c3ec938518df2 Mon Sep 17 00:00:00 2001 From: steve-chavez Date: Sun, 20 Aug 2023 17:27:36 -0500 Subject: [PATCH 2/2] fix: mpc_sepby1 not applying fold correctly `mpc_sepby1` takes a single fold function but this doesn't apply to the whole list of entries. Instead it applies the fold twice, one for `mpc_and` and another for `mpc_many`. Introduce a new repeat repeat parser type MPC_TYPE_SEPBY1 that combines the results and applies the fold once for all entries. --- mpc.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++------ tests/core.c | 18 ++++++++++++ 2 files changed, 91 insertions(+), 8 deletions(-) diff --git a/mpc.c b/mpc.c index c2b0389..0282dd2 100644 --- a/mpc.c +++ b/mpc.c @@ -916,7 +916,9 @@ enum { MPC_TYPE_CHECK_WITH = 26, MPC_TYPE_SOI = 27, - MPC_TYPE_EOI = 28 + MPC_TYPE_EOI = 28, + + MPC_TYPE_SEPBY1 = 29 }; typedef struct { char *m; } mpc_pdata_fail_t; @@ -936,6 +938,7 @@ typedef struct { mpc_parser_t *x; mpc_dtor_t dx; mpc_ctor_t lf; } mpc_pdata_not_ typedef struct { int n; mpc_fold_t f; mpc_parser_t *x; mpc_dtor_t dx; } mpc_pdata_repeat_t; typedef struct { int n; mpc_parser_t **xs; } mpc_pdata_or_t; typedef struct { int n; mpc_fold_t f; mpc_parser_t **xs; mpc_dtor_t *dxs; } mpc_pdata_and_t; +typedef struct { int n; mpc_fold_t f; mpc_parser_t *x; mpc_parser_t *sep; } mpc_pdata_sepby1; typedef union { mpc_pdata_fail_t fail; @@ -955,6 +958,7 @@ typedef union { mpc_pdata_repeat_t repeat; mpc_pdata_and_t and; mpc_pdata_or_t or; + mpc_pdata_sepby1 sepby1; } mpc_pdata_t; struct mpc_parser_t { @@ -1221,6 +1225,35 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e if (j >= MPC_PARSE_STACK_MIN) { mpc_free(i, results); }); } + case MPC_TYPE_SEPBY1: + + results = results_stk; + + if(mpc_parse_run(i, p->data.sepby1.x, &results[j], e, depth+1)){ + j++; + results = mpc_grow_results(i, j, results_stk, results); + + while ( + mpc_parse_run(i, p->data.sepby1.sep, &results[j], e, depth+1) && + mpc_parse_run(i, p->data.sepby1.x, &results[j], e, depth+1) + ) { + j++; + results = mpc_grow_results(i, j, results_stk, results); + } + } + + if (j == 0) { + MPC_FAILURE( + mpc_err_many1(i, results[j].error); + if (j >= MPC_PARSE_STACK_MIN) { mpc_free(i, results); }); + } else { + *e = mpc_err_merge(i, *e, results[j].error); + + MPC_SUCCESS( + mpc_parse_fold(i, p->data.repeat.f, j, (mpc_val_t**)results); + if (j >= MPC_PARSE_STACK_MIN) { mpc_free(i, results); }); + } + case MPC_TYPE_COUNT: results = p->data.repeat.n > MPC_PARSE_STACK_MIN @@ -1268,7 +1301,6 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e if (p->data.or.n > MPC_PARSE_STACK_MIN) { mpc_free(i, results); }); case MPC_TYPE_AND: - if (p->data.and.n == 0) { MPC_SUCCESS(NULL); } results = p->data.or.n > MPC_PARSE_STACK_MIN @@ -1429,6 +1461,11 @@ static void mpc_undefine_unretained(mpc_parser_t *p, int force) { mpc_undefine_unretained(p->data.repeat.x, 0); break; + case MPC_TYPE_SEPBY1: + mpc_undefine_unretained(p->data.sepby1.x, 0); + mpc_undefine_unretained(p->data.sepby1.sep, 0); + break; + case MPC_TYPE_OR: mpc_undefine_or(p); break; case MPC_TYPE_AND: mpc_undefine_and(p); break; @@ -1538,6 +1575,11 @@ mpc_parser_t *mpc_copy(mpc_parser_t *a) { p->data.repeat.x = mpc_copy(a->data.repeat.x); break; + case MPC_TYPE_SEPBY1: + p->data.sepby1.x = mpc_copy(a->data.sepby1.x); + p->data.sepby1.sep = mpc_copy(a->data.sepby1.sep); + break; + case MPC_TYPE_OR: p->data.or.xs = malloc(a->data.or.n * sizeof(mpc_parser_t*)); for (i = 0; i < a->data.or.n; i++) { @@ -1933,6 +1975,15 @@ mpc_parser_t *mpc_count(int n, mpc_fold_t f, mpc_parser_t *a, mpc_dtor_t da) { return p; } +mpc_parser_t *mpc_sepby1(mpc_fold_t f, mpc_parser_t *sep, mpc_parser_t *a) { + mpc_parser_t *p = mpc_undefined(); + p->type = MPC_TYPE_SEPBY1; + p->data.sepby1.x = a; + p->data.sepby1.f = f; + p->data.sepby1.sep = sep; + return p; +} + mpc_parser_t *mpc_or(int n, ...) { int i; @@ -2120,12 +2171,6 @@ mpc_parser_t *mpc_tok_braces(mpc_parser_t *a, mpc_dtor_t ad) { return mpc_tok_ mpc_parser_t *mpc_tok_brackets(mpc_parser_t *a, mpc_dtor_t ad) { return mpc_tok_between(a, ad, "{", "}"); } mpc_parser_t *mpc_tok_squares(mpc_parser_t *a, mpc_dtor_t ad) { return mpc_tok_between(a, ad, "[", "]"); } -mpc_parser_t *mpc_sepby1(mpc_fold_t f, mpc_parser_t *sep, mpc_parser_t *a) { - return mpc_and(2, f, - a, mpc_many(f, mpc_and(2, mpcf_snd_free, sep, mpc_copy(a), free)), - free); -} - /* ** Regular Expression Parsers */ @@ -2771,6 +2816,15 @@ static void mpc_print_unretained(mpc_parser_t *p, int force) { if (p->type == MPC_TYPE_MANY) { mpc_print_unretained(p->data.repeat.x, 0); printf("*"); } if (p->type == MPC_TYPE_MANY1) { mpc_print_unretained(p->data.repeat.x, 0); printf("+"); } if (p->type == MPC_TYPE_COUNT) { mpc_print_unretained(p->data.repeat.x, 0); printf("{%i}", p->data.repeat.n); } + if (p->type == MPC_TYPE_SEPBY1) { + mpc_print_unretained(p->data.sepby1.x, 0); + printf(" ("); + mpc_print_unretained(p->data.sepby1.sep, 0); + printf(" "); + mpc_print_unretained(p->data.sepby1.x, 0); + printf(")"); + printf("*"); + } if (p->type == MPC_TYPE_OR) { printf("("); @@ -3860,6 +3914,13 @@ static int mpc_nodecount_unretained(mpc_parser_t* p, int force) { if (p->type == MPC_TYPE_MANY) { return 1 + mpc_nodecount_unretained(p->data.repeat.x, 0); } if (p->type == MPC_TYPE_MANY1) { return 1 + mpc_nodecount_unretained(p->data.repeat.x, 0); } if (p->type == MPC_TYPE_COUNT) { return 1 + mpc_nodecount_unretained(p->data.repeat.x, 0); } + if (p->type == MPC_TYPE_SEPBY1) { + total = 1; + total += mpc_nodecount_unretained(p->data.sepby1.x, 0); + total += mpc_nodecount_unretained(p->data.sepby1.sep, 0); + total += mpc_nodecount_unretained(p->data.sepby1.x, 0); + return total; + } if (p->type == MPC_TYPE_OR) { total = 1; @@ -3907,6 +3968,10 @@ static void mpc_optimise_unretained(mpc_parser_t *p, int force) { if (p->type == MPC_TYPE_MANY) { mpc_optimise_unretained(p->data.repeat.x, 0); } if (p->type == MPC_TYPE_MANY1) { mpc_optimise_unretained(p->data.repeat.x, 0); } if (p->type == MPC_TYPE_COUNT) { mpc_optimise_unretained(p->data.repeat.x, 0); } + if (p->type == MPC_TYPE_SEPBY1) { + mpc_optimise_unretained(p->data.sepby1.x, 0); + mpc_optimise_unretained(p->data.sepby1.sep, 0); + } if (p->type == MPC_TYPE_OR) { for(i = 0; i < p->data.or.n; i++) { diff --git a/tests/core.c b/tests/core.c index 35e1411..eda48eb 100644 --- a/tests/core.c +++ b/tests/core.c @@ -8,6 +8,11 @@ static int int_eq(const void* x, const void* y) { return (*(int*)x == *(int*)y); static void int_print(const void* x) { printf("'%i'", *((int*)x)); } static int streq(const void* x, const void* y) { return (strcmp(x, y) == 0); } static void strprint(const void* x) { printf("'%s'", (char*)x); } +static mpc_val_t *fold_vals(int n, mpc_val_t **xs) { + char** vals = malloc(sizeof(char*) * n); + memcpy(vals, xs, sizeof(char*) * n); + return vals; +} void test_ident(void) { @@ -252,6 +257,19 @@ void test_sepby(void) { PT_ASSERT(mpc_test_pass(CommaSepIdent, "one,two,three", "onetwothree", streq, free, strprint)); mpc_delete(CommaSepIdent); + + mpc_parser_t* CommaSepIdent1 = mpc_sepby1(fold_vals, mpc_char(','), mpc_ident()); + mpc_result_t r; + + mpc_parse("", "uno,dos,tres,cuatro", CommaSepIdent1, &r); + char **vals = r.output; + PT_ASSERT(strcmp("uno", vals[0]) == 0); + PT_ASSERT(strcmp("dos", vals[1]) == 0); + PT_ASSERT(strcmp("tres", vals[2]) == 0); + PT_ASSERT(strcmp("cuatro", vals[3]) == 0); + + free(vals); + mpc_delete(CommaSepIdent1); } void suite_core(void) {