Adjust the behaviour of mpc_eoi so that it only is successful in matching the end of input once.
This commit is contained in:
@@ -672,6 +672,7 @@ Fold Functions
|
|||||||
<tr><td><code>mpc_val_t *mpcf_fst_free(int n, mpc_val_t** xs);</code></td><td>Returns first element of <code>xs</code> and calls <code>free</code> on others</td></tr>
|
<tr><td><code>mpc_val_t *mpcf_fst_free(int n, mpc_val_t** xs);</code></td><td>Returns first element of <code>xs</code> and calls <code>free</code> on others</td></tr>
|
||||||
<tr><td><code>mpc_val_t *mpcf_snd_free(int n, mpc_val_t** xs);</code></td><td>Returns second element of <code>xs</code> and calls <code>free</code> on others</td></tr>
|
<tr><td><code>mpc_val_t *mpcf_snd_free(int n, mpc_val_t** xs);</code></td><td>Returns second element of <code>xs</code> and calls <code>free</code> on others</td></tr>
|
||||||
<tr><td><code>mpc_val_t *mpcf_trd_free(int n, mpc_val_t** xs);</code></td><td>Returns third element of <code>xs</code> and calls <code>free</code> on others</td></tr>
|
<tr><td><code>mpc_val_t *mpcf_trd_free(int n, mpc_val_t** xs);</code></td><td>Returns third element of <code>xs</code> and calls <code>free</code> on others</td></tr>
|
||||||
|
<tr><td><code>mpc_val_t *mpcf_freefold(int n, mpc_val_t** xs);</code></td><td>Calls <code>free</code> on all elements of <code>xs</code> and returns <code>NULL</code></td></tr>
|
||||||
<tr><td><code>mpc_val_t *mpcf_strfold(int n, mpc_val_t** xs);</code></td><td>Concatenates all <code>xs</code> together as strings and returns result </td></tr>
|
<tr><td><code>mpc_val_t *mpcf_strfold(int n, mpc_val_t** xs);</code></td><td>Concatenates all <code>xs</code> together as strings and returns result </td></tr>
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
|
51
mpc.c
51
mpc.c
@@ -9,6 +9,7 @@ static mpc_state_t mpc_state_invalid(void) {
|
|||||||
s.pos = -1;
|
s.pos = -1;
|
||||||
s.row = -1;
|
s.row = -1;
|
||||||
s.col = -1;
|
s.col = -1;
|
||||||
|
s.term = 0;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,6 +18,7 @@ static mpc_state_t mpc_state_new(void) {
|
|||||||
s.pos = 0;
|
s.pos = 0;
|
||||||
s.row = 0;
|
s.row = 0;
|
||||||
s.col = 0;
|
s.col = 0;
|
||||||
|
s.term = 0;
|
||||||
return s;
|
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));
|
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) {
|
static mpc_state_t *mpc_input_state_copy(mpc_input_t *i) {
|
||||||
mpc_state_t *r = mpc_malloc(i, sizeof(mpc_state_t));
|
mpc_state_t *r = mpc_malloc(i, sizeof(mpc_state_t));
|
||||||
memcpy(r, &i->state, sizeof(mpc_state_t));
|
memcpy(r, &i->state, sizeof(mpc_state_t));
|
||||||
@@ -885,7 +904,10 @@ enum {
|
|||||||
MPC_TYPE_AND = 24,
|
MPC_TYPE_AND = 24,
|
||||||
|
|
||||||
MPC_TYPE_CHECK = 25,
|
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;
|
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_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_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_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 */
|
/* 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);
|
*e = mpc_err_merge(i, *e, results[j].error);
|
||||||
|
|
||||||
MPC_SUCCESS(
|
MPC_SUCCESS(
|
||||||
mpc_parse_fold(i, p->data.repeat.f, j, (mpc_val_t**)results);
|
mpc_parse_fold(i, p->data.repeat.f, j, (mpc_val_t**)results);
|
||||||
if (j >= MPC_PARSE_STACK_MIN) { mpc_free(i, 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);
|
mpc_err_many1(i, results[j].error);
|
||||||
if (j >= MPC_PARSE_STACK_MIN) { mpc_free(i, results); });
|
if (j >= MPC_PARSE_STACK_MIN) { mpc_free(i, results); });
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
*e = mpc_err_merge(i, *e, results[j].error);
|
*e = mpc_err_merge(i, *e, results[j].error);
|
||||||
|
|
||||||
MPC_SUCCESS(
|
MPC_SUCCESS(
|
||||||
mpc_parse_fold(i, p->data.repeat.f, j, (mpc_val_t**)results);
|
mpc_parse_fold(i, p->data.repeat.f, j, (mpc_val_t**)results);
|
||||||
if (j >= MPC_PARSE_STACK_MIN) { mpc_free(i, 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
|
** Common Parsers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int mpc_soi_anchor(char prev, char next) { (void) next; return (prev == '\0'); }
|
mpc_parser_t *mpc_soi(void) {
|
||||||
static int mpc_eoi_anchor(char prev, char next) { (void) prev; return (next == '\0'); }
|
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) {
|
||||||
mpc_parser_t *mpc_eoi(void) { return mpc_expect(mpc_anchor(mpc_eoi_anchor), "end of input"); }
|
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) {
|
static int mpc_boundary_anchor(char prev, char next) {
|
||||||
const char* word = "abcdefghijklmnopqrstuvwxyz"
|
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_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_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) {
|
mpc_val_t *mpcf_strfold(int n, mpc_val_t **xs) {
|
||||||
int i;
|
int i;
|
||||||
size_t l = 0;
|
size_t l = 0;
|
||||||
|
2
mpc.h
2
mpc.h
@@ -30,6 +30,7 @@ typedef struct {
|
|||||||
long pos;
|
long pos;
|
||||||
long row;
|
long row;
|
||||||
long col;
|
long col;
|
||||||
|
int term;
|
||||||
} mpc_state_t;
|
} 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_fst_free(int n, mpc_val_t** xs);
|
||||||
mpc_val_t *mpcf_snd_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_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_strfold(int n, mpc_val_t** xs);
|
||||||
mpc_val_t *mpcf_maths(int n, mpc_val_t** xs);
|
mpc_val_t *mpcf_maths(int n, mpc_val_t** xs);
|
||||||
|
@@ -10,7 +10,7 @@ static int check_is(mpc_val_t** x, void* t) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void test_check(void) {
|
void test_check(void) {
|
||||||
int success;
|
int success;
|
||||||
mpc_result_t r;
|
mpc_result_t r;
|
||||||
mpc_parser_t* p = mpc_check(mpc_or(2, mpc_char('a'), mpc_char('b')), check_is_a, "Expected 'a'");
|
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) {
|
void test_check_with(void) {
|
||||||
int success;
|
int success;
|
||||||
mpc_result_t r;
|
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);
|
success = mpc_parse("test", "a", p, &r);
|
||||||
PT_ASSERT(success);
|
PT_ASSERT(success);
|
||||||
@@ -46,7 +46,7 @@ void test_check_with(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void test_checkf(void) {
|
void test_checkf(void) {
|
||||||
int success;
|
int success;
|
||||||
mpc_result_t r;
|
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");
|
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) {
|
void test_check_withf(void) {
|
||||||
int success;
|
int success;
|
||||||
mpc_result_t r;
|
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);
|
success = mpc_parse("test", "a", p, &r);
|
||||||
PT_ASSERT(success);
|
PT_ASSERT(success);
|
||||||
|
34
tests/core.c
34
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) {
|
void suite_core(void) {
|
||||||
pt_add_test(test_ident, "Test Ident", "Suite Core");
|
pt_add_test(test_ident, "Test Ident", "Suite Core");
|
||||||
pt_add_test(test_maths, "Test Maths", "Suite Core");
|
pt_add_test(test_maths, "Test Maths", "Suite Core");
|
||||||
pt_add_test(test_strip, "Test Strip", "Suite Core");
|
pt_add_test(test_strip, "Test Strip", "Suite Core");
|
||||||
pt_add_test(test_repeat, "Test Repeat", "Suite Core");
|
pt_add_test(test_repeat, "Test Repeat", "Suite Core");
|
||||||
pt_add_test(test_copy, "Test Copy", "Suite Core");
|
pt_add_test(test_copy, "Test Copy", "Suite Core");
|
||||||
|
pt_add_test(test_reader, "Test Reader", "Suite Core");
|
||||||
}
|
}
|
||||||
|
@@ -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) {
|
void suite_regex(void) {
|
||||||
pt_add_test(test_regex_basic, "Test Regex Basic", "Suite Regex");
|
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_range, "Test Regex Range", "Suite Regex");
|
||||||
pt_add_test(test_regex_string, "Test Regex String", "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_lisp_comment, "Test Regex Lisp Comment", "Suite Regex");
|
||||||
pt_add_test(test_regex_boundary, "Test Regex Boundary", "Suite Regex");
|
pt_add_test(test_regex_boundary, "Test Regex Boundary", "Suite Regex");
|
||||||
|
pt_add_test(test_regex_newline, "Test Regex Newline", "Suite Regex");
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user