From 4da2ae5febfcce003310a0cd2af810272b3a4fa0 Mon Sep 17 00:00:00 2001 From: Daniel Holden Date: Thu, 3 Mar 2016 10:34:52 +0000 Subject: [PATCH] Updated copy function to work properly with larger parsers --- mpc.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++- tests/core.c | 39 +++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/mpc.c b/mpc.c index cc0267a..9e84a47 100644 --- a/mpc.c +++ b/mpc.c @@ -1365,14 +1365,77 @@ mpc_parser_t *mpc_new(const char *name) { } mpc_parser_t *mpc_copy(mpc_parser_t *a) { - mpc_parser_t *p = mpc_undefined(); + int i = 0; + mpc_parser_t *p; + + if (a->retained) { return a; } + + p = mpc_undefined(); p->retained = a->retained; p->type = a->type; p->data = a->data; + if (a->name) { p->name = malloc(strlen(a->name)+1); strcpy(p->name, a->name); } + + switch (a->type) { + + case MPC_TYPE_FAIL: + p->data.fail.m = malloc(strlen(a->data.fail.m)+1); + strcpy(p->data.fail.m, a->data.fail.m); + break; + + case MPC_TYPE_ONEOF: + case MPC_TYPE_NONEOF: + case MPC_TYPE_STRING: + p->data.string.x = malloc(strlen(a->data.string.x)+1); + strcpy(p->data.string.x, a->data.string.x); + break; + + case MPC_TYPE_APPLY: p->data.apply.x = mpc_copy(a->data.apply.x); break; + case MPC_TYPE_APPLY_TO: p->data.apply_to.x = mpc_copy(a->data.apply_to.x); break; + case MPC_TYPE_PREDICT: p->data.predict.x = mpc_copy(a->data.predict.x); break; + + case MPC_TYPE_MAYBE: + case MPC_TYPE_NOT: + p->data.not.x = mpc_copy(a->data.not.x); + break; + + case MPC_TYPE_EXPECT: + p->data.expect.x = mpc_copy(a->data.expect.x); + p->data.expect.m = malloc(strlen(a->data.expect.m)+1); + strcpy(p->data.expect.m, a->data.expect.m); + break; + + case MPC_TYPE_MANY: + case MPC_TYPE_MANY1: + case MPC_TYPE_COUNT: + p->data.repeat.x = mpc_copy(a->data.repeat.x); + 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++) { + p->data.or.xs[i] = mpc_copy(a->data.or.xs[i]); + } + break; + case MPC_TYPE_AND: + p->data.and.xs = malloc(a->data.and.n * sizeof(mpc_parser_t*)); + for (i = 0; i < a->data.and.n; i++) { + p->data.and.xs[i] = mpc_copy(a->data.and.xs[i]); + } + p->data.and.dxs = malloc((a->data.and.n-1) * sizeof(mpc_dtor_t)); + for (i = 0; i < a->data.and.n-1; i++) { + p->data.and.dxs[i] = a->data.and.dxs[i]; + } + break; + + default: break; + } + + return p; } diff --git a/tests/core.c b/tests/core.c index de4a3e6..06d7f71 100644 --- a/tests/core.c +++ b/tests/core.c @@ -114,9 +114,48 @@ void test_repeat(void) { } +void test_copy(void) { + + int success; + mpc_result_t r; + mpc_parser_t* p = mpc_or(2, mpc_char('a'), mpc_char('b')); + mpc_parser_t* q = mpc_and(2, mpcf_strfold, p, mpc_copy(p), free); + + success = mpc_parse("test", "aa", q, &r); + PT_ASSERT(success); + PT_ASSERT_STR_EQ(r.output, "aa"); + free(r.output); + + success = mpc_parse("test", "bb", q, &r); + PT_ASSERT(success); + PT_ASSERT_STR_EQ(r.output, "bb"); + free(r.output); + + success = mpc_parse("test", "ab", q, &r); + PT_ASSERT(success); + PT_ASSERT_STR_EQ(r.output, "ab"); + free(r.output); + + success = mpc_parse("test", "ba", q, &r); + PT_ASSERT(success); + PT_ASSERT_STR_EQ(r.output, "ba"); + free(r.output); + + success = mpc_parse("test", "c", p, &r); + PT_ASSERT(!success); + mpc_err_delete(r.error); + + mpc_delete(mpc_copy(p)); + mpc_delete(mpc_copy(q)); + + mpc_delete(q); + +} + void suite_core(void) { pt_add_test(test_ident, "Test Ident", "Suite Core"); pt_add_test(test_maths, "Test Maths", "Suite Core"); pt_add_test(test_strip, "Test Strip", "Suite Core"); pt_add_test(test_repeat, "Test Repeat", "Suite Core"); + pt_add_test(test_copy, "Test Copy", "Suite Core"); }