Skip to content

Commit b866236

Browse files
committedAug 21, 2023
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.
1 parent b7ee5df commit b866236

File tree

2 files changed

+91
-8
lines changed

2 files changed

+91
-8
lines changed
 

‎mpc.c

+73-8
Original file line numberDiff line numberDiff line change
@@ -916,7 +916,9 @@ enum {
916916
MPC_TYPE_CHECK_WITH = 26,
917917

918918
MPC_TYPE_SOI = 27,
919-
MPC_TYPE_EOI = 28
919+
MPC_TYPE_EOI = 28,
920+
921+
MPC_TYPE_SEPBY1 = 29
920922
};
921923

922924
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_
936938
typedef struct { int n; mpc_fold_t f; mpc_parser_t *x; mpc_dtor_t dx; } mpc_pdata_repeat_t;
937939
typedef struct { int n; mpc_parser_t **xs; } mpc_pdata_or_t;
938940
typedef struct { int n; mpc_fold_t f; mpc_parser_t **xs; mpc_dtor_t *dxs; } mpc_pdata_and_t;
941+
typedef struct { int n; mpc_fold_t f; mpc_parser_t *x; mpc_parser_t *sep; } mpc_pdata_sepby1;
939942

940943
typedef union {
941944
mpc_pdata_fail_t fail;
@@ -955,6 +958,7 @@ typedef union {
955958
mpc_pdata_repeat_t repeat;
956959
mpc_pdata_and_t and;
957960
mpc_pdata_or_t or;
961+
mpc_pdata_sepby1 sepby1;
958962
} mpc_pdata_t;
959963

960964
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
12211225
if (j >= MPC_PARSE_STACK_MIN) { mpc_free(i, results); });
12221226
}
12231227

1228+
case MPC_TYPE_SEPBY1:
1229+
1230+
results = results_stk;
1231+
1232+
if(mpc_parse_run(i, p->data.sepby1.x, &results[j], e, depth+1)){
1233+
j++;
1234+
results = mpc_grow_results(i, j, results_stk, results);
1235+
1236+
while (
1237+
mpc_parse_run(i, p->data.sepby1.sep, &results[j], e, depth+1) &&
1238+
mpc_parse_run(i, p->data.sepby1.x, &results[j], e, depth+1)
1239+
) {
1240+
j++;
1241+
results = mpc_grow_results(i, j, results_stk, results);
1242+
}
1243+
}
1244+
1245+
if (j == 0) {
1246+
MPC_FAILURE(
1247+
mpc_err_many1(i, results[j].error);
1248+
if (j >= MPC_PARSE_STACK_MIN) { mpc_free(i, results); });
1249+
} else {
1250+
*e = mpc_err_merge(i, *e, results[j].error);
1251+
1252+
MPC_SUCCESS(
1253+
mpc_parse_fold(i, p->data.repeat.f, j, (mpc_val_t**)results);
1254+
if (j >= MPC_PARSE_STACK_MIN) { mpc_free(i, results); });
1255+
}
1256+
12241257
case MPC_TYPE_COUNT:
12251258

12261259
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
12681301
if (p->data.or.n > MPC_PARSE_STACK_MIN) { mpc_free(i, results); });
12691302

12701303
case MPC_TYPE_AND:
1271-
12721304
if (p->data.and.n == 0) { MPC_SUCCESS(NULL); }
12731305

12741306
results = p->data.or.n > MPC_PARSE_STACK_MIN
@@ -1429,6 +1461,11 @@ static void mpc_undefine_unretained(mpc_parser_t *p, int force) {
14291461
mpc_undefine_unretained(p->data.repeat.x, 0);
14301462
break;
14311463

1464+
case MPC_TYPE_SEPBY1:
1465+
mpc_undefine_unretained(p->data.sepby1.x, 0);
1466+
mpc_undefine_unretained(p->data.sepby1.sep, 0);
1467+
break;
1468+
14321469
case MPC_TYPE_OR: mpc_undefine_or(p); break;
14331470
case MPC_TYPE_AND: mpc_undefine_and(p); break;
14341471

@@ -1538,6 +1575,11 @@ mpc_parser_t *mpc_copy(mpc_parser_t *a) {
15381575
p->data.repeat.x = mpc_copy(a->data.repeat.x);
15391576
break;
15401577

1578+
case MPC_TYPE_SEPBY1:
1579+
p->data.sepby1.x = mpc_copy(a->data.sepby1.x);
1580+
p->data.sepby1.sep = mpc_copy(a->data.sepby1.sep);
1581+
break;
1582+
15411583
case MPC_TYPE_OR:
15421584
p->data.or.xs = malloc(a->data.or.n * sizeof(mpc_parser_t*));
15431585
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) {
19331975
return p;
19341976
}
19351977

1978+
mpc_parser_t *mpc_sepby1(mpc_fold_t f, mpc_parser_t *sep, mpc_parser_t *a) {
1979+
mpc_parser_t *p = mpc_undefined();
1980+
p->type = MPC_TYPE_SEPBY1;
1981+
p->data.sepby1.x = a;
1982+
p->data.sepby1.f = f;
1983+
p->data.sepby1.sep = sep;
1984+
return p;
1985+
}
1986+
19361987
mpc_parser_t *mpc_or(int n, ...) {
19371988

19381989
int i;
@@ -2120,12 +2171,6 @@ mpc_parser_t *mpc_tok_braces(mpc_parser_t *a, mpc_dtor_t ad) { return mpc_tok_
21202171
mpc_parser_t *mpc_tok_brackets(mpc_parser_t *a, mpc_dtor_t ad) { return mpc_tok_between(a, ad, "{", "}"); }
21212172
mpc_parser_t *mpc_tok_squares(mpc_parser_t *a, mpc_dtor_t ad) { return mpc_tok_between(a, ad, "[", "]"); }
21222173

2123-
mpc_parser_t *mpc_sepby1(mpc_fold_t f, mpc_parser_t *sep, mpc_parser_t *a) {
2124-
return mpc_and(2, f,
2125-
a, mpc_many(f, mpc_and(2, mpcf_snd_free, sep, mpc_copy(a), free)),
2126-
free);
2127-
}
2128-
21292174
/*
21302175
** Regular Expression Parsers
21312176
*/
@@ -2771,6 +2816,15 @@ static void mpc_print_unretained(mpc_parser_t *p, int force) {
27712816
if (p->type == MPC_TYPE_MANY) { mpc_print_unretained(p->data.repeat.x, 0); printf("*"); }
27722817
if (p->type == MPC_TYPE_MANY1) { mpc_print_unretained(p->data.repeat.x, 0); printf("+"); }
27732818
if (p->type == MPC_TYPE_COUNT) { mpc_print_unretained(p->data.repeat.x, 0); printf("{%i}", p->data.repeat.n); }
2819+
if (p->type == MPC_TYPE_SEPBY1) {
2820+
mpc_print_unretained(p->data.sepby1.x, 0);
2821+
printf(" (");
2822+
mpc_print_unretained(p->data.sepby1.sep, 0);
2823+
printf(" ");
2824+
mpc_print_unretained(p->data.sepby1.x, 0);
2825+
printf(")");
2826+
printf("*");
2827+
}
27742828

27752829
if (p->type == MPC_TYPE_OR) {
27762830
printf("(");
@@ -3860,6 +3914,13 @@ static int mpc_nodecount_unretained(mpc_parser_t* p, int force) {
38603914
if (p->type == MPC_TYPE_MANY) { return 1 + mpc_nodecount_unretained(p->data.repeat.x, 0); }
38613915
if (p->type == MPC_TYPE_MANY1) { return 1 + mpc_nodecount_unretained(p->data.repeat.x, 0); }
38623916
if (p->type == MPC_TYPE_COUNT) { return 1 + mpc_nodecount_unretained(p->data.repeat.x, 0); }
3917+
if (p->type == MPC_TYPE_SEPBY1) {
3918+
total = 1;
3919+
total += mpc_nodecount_unretained(p->data.sepby1.x, 0);
3920+
total += mpc_nodecount_unretained(p->data.sepby1.sep, 0);
3921+
total += mpc_nodecount_unretained(p->data.sepby1.x, 0);
3922+
return total;
3923+
}
38633924

38643925
if (p->type == MPC_TYPE_OR) {
38653926
total = 1;
@@ -3907,6 +3968,10 @@ static void mpc_optimise_unretained(mpc_parser_t *p, int force) {
39073968
if (p->type == MPC_TYPE_MANY) { mpc_optimise_unretained(p->data.repeat.x, 0); }
39083969
if (p->type == MPC_TYPE_MANY1) { mpc_optimise_unretained(p->data.repeat.x, 0); }
39093970
if (p->type == MPC_TYPE_COUNT) { mpc_optimise_unretained(p->data.repeat.x, 0); }
3971+
if (p->type == MPC_TYPE_SEPBY1) {
3972+
mpc_optimise_unretained(p->data.sepby1.x, 0);
3973+
mpc_optimise_unretained(p->data.sepby1.sep, 0);
3974+
}
39103975

39113976
if (p->type == MPC_TYPE_OR) {
39123977
for(i = 0; i < p->data.or.n; i++) {

‎tests/core.c

+18
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ static int int_eq(const void* x, const void* y) { return (*(int*)x == *(int*)y);
88
static void int_print(const void* x) { printf("'%i'", *((int*)x)); }
99
static int streq(const void* x, const void* y) { return (strcmp(x, y) == 0); }
1010
static void strprint(const void* x) { printf("'%s'", (char*)x); }
11+
static mpc_val_t *fold_vals(int n, mpc_val_t **xs) {
12+
char** vals = malloc(sizeof(char*) * n);
13+
memcpy(vals, xs, sizeof(char*) * n);
14+
return vals;
15+
}
1116

1217
void test_ident(void) {
1318

@@ -252,6 +257,19 @@ void test_sepby(void) {
252257
PT_ASSERT(mpc_test_pass(CommaSepIdent, "one,two,three", "onetwothree", streq, free, strprint));
253258

254259
mpc_delete(CommaSepIdent);
260+
261+
mpc_parser_t* CommaSepIdent1 = mpc_sepby1(fold_vals, mpc_char(','), mpc_ident());
262+
mpc_result_t r;
263+
264+
mpc_parse("<test>", "uno,dos,tres,cuatro", CommaSepIdent1, &r);
265+
char **vals = r.output;
266+
PT_ASSERT(strcmp("uno", vals[0]) == 0);
267+
PT_ASSERT(strcmp("dos", vals[1]) == 0);
268+
PT_ASSERT(strcmp("tres", vals[2]) == 0);
269+
PT_ASSERT(strcmp("cuatro", vals[3]) == 0);
270+
271+
free(vals);
272+
mpc_delete(CommaSepIdent1);
255273
}
256274

257275
void suite_core(void) {

0 commit comments

Comments
 (0)