From 65060137b184dc2c9b73adcddb2b2b8cd2e4fc82 Mon Sep 17 00:00:00 2001 From: Daniel Holden Date: Sat, 13 Oct 2018 17:35:21 -0400 Subject: [PATCH] Adjust the behaviour of mpc_eoi so that it only is successful in matching the end of input once. --- README.md | 1 + mpc.c | 51 ++++++++++++++++++++++++++++++++++++++++----- mpc.h | 2 ++ tests/combinators.c | 12 +++++------ tests/core.c | 34 ++++++++++++++++++++++++++++++ tests/regex.c | 13 ++++++++++++ 6 files changed, 102 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index d251f26..e5f387d 100644 --- a/README.md +++ b/README.md @@ -672,6 +672,7 @@ Fold Functions mpc_val_t *mpcf_fst_free(int n, mpc_val_t** xs);Returns first element of xs and calls free on others mpc_val_t *mpcf_snd_free(int n, mpc_val_t** xs);Returns second element of xs and calls free on others mpc_val_t *mpcf_trd_free(int n, mpc_val_t** xs);Returns third element of xs and calls free on others + mpc_val_t *mpcf_freefold(int n, mpc_val_t** xs);Calls free on all elements of xs and returns NULL mpc_val_t *mpcf_strfold(int n, mpc_val_t** xs);Concatenates all xs together as strings and returns result diff --git a/mpc.c b/mpc.c index 142c6fe..f19371a 100644 --- a/mpc.c +++ b/mpc.c @@ -9,6 +9,7 @@ static mpc_state_t mpc_state_invalid(void) { s.pos = -1; s.row = -1; s.col = -1; + s.term = 0; return s; } @@ -17,6 +18,7 @@ static mpc_state_t mpc_state_new(void) { s.pos = 0; s.row = 0; s.col = 0; + s.term = 0; return s; } @@ -536,6 +538,23 @@ static int mpc_input_anchor(mpc_input_t* i, int(*f)(char,char), char **o) { return f(i->last, mpc_input_peekc(i)); } +static int mpc_input_soi(mpc_input_t* i, char **o) { + *o = NULL; + return i->last == '\0'; +} + +static int mpc_input_eoi(mpc_input_t* i, char **o) { + *o = NULL; + if (i->state.term) { + return 0; + } else if (mpc_input_terminated(i)) { + i->state.term = 1; + return 1; + } else { + return 0; + } +} + static mpc_state_t *mpc_input_state_copy(mpc_input_t *i) { mpc_state_t *r = mpc_malloc(i, sizeof(mpc_state_t)); memcpy(r, &i->state, sizeof(mpc_state_t)); @@ -885,7 +904,10 @@ enum { MPC_TYPE_AND = 24, MPC_TYPE_CHECK = 25, - MPC_TYPE_CHECK_WITH = 26 + MPC_TYPE_CHECK_WITH = 26, + + MPC_TYPE_SOI = 27, + MPC_TYPE_EOI = 28 }; typedef struct { char *m; } mpc_pdata_fail_t; @@ -1032,6 +1054,8 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e case MPC_TYPE_SATISFY: MPC_PRIMITIVE(mpc_input_satisfy(i, p->data.satisfy.f, (char**)&r->output)); case MPC_TYPE_STRING: MPC_PRIMITIVE(mpc_input_string(i, p->data.string.x, (char**)&r->output)); case MPC_TYPE_ANCHOR: MPC_PRIMITIVE(mpc_input_anchor(i, p->data.anchor.f, (char**)&r->output)); + case MPC_TYPE_SOI: MPC_PRIMITIVE(mpc_input_soi(i, (char**)&r->output)); + case MPC_TYPE_EOI: MPC_PRIMITIVE(mpc_input_eoi(i, (char**)&r->output)); /* Other parsers */ @@ -1145,6 +1169,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e } *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); }); @@ -1170,7 +1195,9 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e 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); }); @@ -1929,11 +1956,17 @@ mpc_parser_t *mpc_and(int n, mpc_fold_t f, ...) { ** Common Parsers */ -static int mpc_soi_anchor(char prev, char next) { (void) next; return (prev == '\0'); } -static int mpc_eoi_anchor(char prev, char next) { (void) prev; return (next == '\0'); } +mpc_parser_t *mpc_soi(void) { + mpc_parser_t *p = mpc_undefined(); + p->type = MPC_TYPE_SOI; + return mpc_expect(p, "start of input"); +} -mpc_parser_t *mpc_soi(void) { return mpc_expect(mpc_anchor(mpc_soi_anchor), "start of input"); } -mpc_parser_t *mpc_eoi(void) { return mpc_expect(mpc_anchor(mpc_eoi_anchor), "end of input"); } +mpc_parser_t *mpc_eoi(void) { + mpc_parser_t *p = mpc_undefined(); + p->type = MPC_TYPE_EOI; + return mpc_expect(p, "end of input"); +} static int mpc_boundary_anchor(char prev, char next) { const char* word = "abcdefghijklmnopqrstuvwxyz" @@ -2547,6 +2580,14 @@ mpc_val_t *mpcf_fst_free(int n, mpc_val_t **xs) { return mpcf_nth_free(n, xs, 0) mpc_val_t *mpcf_snd_free(int n, mpc_val_t **xs) { return mpcf_nth_free(n, xs, 1); } mpc_val_t *mpcf_trd_free(int n, mpc_val_t **xs) { return mpcf_nth_free(n, xs, 2); } +mpc_val_t *mpcf_freefold(int n, mpc_val_t **xs) { + int i; + for (i = 0; i < n; i++) { + free(xs[i]); + } + return NULL; +} + mpc_val_t *mpcf_strfold(int n, mpc_val_t **xs) { int i; size_t l = 0; diff --git a/mpc.h b/mpc.h index e6ef289..1e85f90 100644 --- a/mpc.h +++ b/mpc.h @@ -30,6 +30,7 @@ typedef struct { long pos; long row; long col; + int term; } mpc_state_t; /* @@ -254,6 +255,7 @@ mpc_val_t *mpcf_trd(int n, mpc_val_t** xs); mpc_val_t *mpcf_fst_free(int n, mpc_val_t** xs); mpc_val_t *mpcf_snd_free(int n, mpc_val_t** xs); mpc_val_t *mpcf_trd_free(int n, mpc_val_t** xs); +mpc_val_t *mpcf_all_free(int n, mpc_val_t** xs); mpc_val_t *mpcf_strfold(int n, mpc_val_t** xs); mpc_val_t *mpcf_maths(int n, mpc_val_t** xs); diff --git a/tests/combinators.c b/tests/combinators.c index 72a2df6..d9fe203 100644 --- a/tests/combinators.c +++ b/tests/combinators.c @@ -10,7 +10,7 @@ static int check_is(mpc_val_t** x, void* t) { } void test_check(void) { - int success; + int success; mpc_result_t r; mpc_parser_t* p = mpc_check(mpc_or(2, mpc_char('a'), mpc_char('b')), check_is_a, "Expected 'a'"); @@ -28,9 +28,9 @@ void test_check(void) { } void test_check_with(void) { - int success; + int success; mpc_result_t r; - mpc_parser_t* p = mpc_check_with(mpc_or(2, mpc_char('a'), mpc_char('b')), check_is, "a", "Expected 'a'"); + mpc_parser_t* p = mpc_check_with(mpc_or(2, mpc_char('a'), mpc_char('b')), check_is, (void*)"a", "Expected 'a'"); success = mpc_parse("test", "a", p, &r); PT_ASSERT(success); @@ -46,7 +46,7 @@ void test_check_with(void) { } void test_checkf(void) { - int success; + int success; mpc_result_t r; mpc_parser_t* p = mpc_checkf(mpc_or(2, mpc_char('a'), mpc_char('b')), check_is_a, "Expected '%s'", "a"); @@ -64,9 +64,9 @@ void test_checkf(void) { } void test_check_withf(void) { - int success; + int success; mpc_result_t r; - mpc_parser_t* p = mpc_check_withf(mpc_or(2, mpc_char('a'), mpc_char('b')), check_is, "a", "Expected '%s'", "a"); + mpc_parser_t* p = mpc_check_withf(mpc_or(2, mpc_char('a'), mpc_char('b')), check_is, (void*)"a", "Expected '%s'", "a"); success = mpc_parse("test", "a", p, &r); PT_ASSERT(success); diff --git a/tests/core.c b/tests/core.c index 06d7f71..3a4bd90 100644 --- a/tests/core.c +++ b/tests/core.c @@ -152,10 +152,44 @@ void test_copy(void) { } +static int line_count = 0; + +static void* read_line(void* line) { + line_count++; + return line; +} + +void test_reader(void) { + + mpc_parser_t* Line = mpc_many( + mpcf_strfold, + mpc_apply(mpc_re("[^\\n]*(\\n|$)"), read_line)); + + line_count = 0; + + PT_ASSERT(mpc_test_pass(Line, + "hello\nworld\n\nthis\nis\ndan", + "hello\nworld\n\nthis\nis\ndan", streq, free, strprint)); + + PT_ASSERT(line_count == 6); + + line_count = 0; + + PT_ASSERT(mpc_test_pass(Line, + "abcHVwufvyuevuy3y436782\n\n\nrehre\nrew\n-ql.;qa\neg", + "abcHVwufvyuevuy3y436782\n\n\nrehre\nrew\n-ql.;qa\neg", streq, free, strprint)); + + PT_ASSERT(line_count == 7); + + mpc_delete(Line); + +} + 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"); + pt_add_test(test_reader, "Test Reader", "Suite Core"); } diff --git a/tests/regex.c b/tests/regex.c index 3446475..40f7ea1 100644 --- a/tests/regex.c +++ b/tests/regex.c @@ -120,10 +120,23 @@ void test_regex_lisp_comment(void) { } +void test_regex_newline(void) { + + mpc_parser_t *re0 = mpc_re("[a-z]*"); + + PT_ASSERT(regex_test_pass(re0, "hi", "hi")); + PT_ASSERT(regex_test_pass(re0, "hi\nk", "hi")); + PT_ASSERT(regex_test_fail(re0, "hi\nk", "hi\nk")); + + mpc_delete(re0); + +} + void suite_regex(void) { pt_add_test(test_regex_basic, "Test Regex Basic", "Suite Regex"); pt_add_test(test_regex_range, "Test Regex Range", "Suite Regex"); pt_add_test(test_regex_string, "Test Regex String", "Suite Regex"); pt_add_test(test_regex_lisp_comment, "Test Regex Lisp Comment", "Suite Regex"); pt_add_test(test_regex_boundary, "Test Regex Boundary", "Suite Regex"); + pt_add_test(test_regex_newline, "Test Regex Newline", "Suite Regex"); }