Merge github.com:orangeduck/mpc

This commit is contained in:
Daniel Holden
2020-07-19 08:54:16 -04:00
11 changed files with 830 additions and 758 deletions

1
.gitignore vendored
View File

@@ -8,3 +8,4 @@ examples/maths
examples/smallc
examples/foobar
examples/tree_traversal
build/*

View File

@@ -1,7 +1,10 @@
CC = gcc
STND=-ansi
CFLAGS = $(STND) -pedantic -O3 -g -Wall -Werror -Wextra -Wformat=2 -Wshadow \
PROJ = mpc
CC ?= gcc
STD ?= -ansi
DIST = build
MKDIR ?= mkdir -p
PREFIX ?= /usr/local
CFLAGS ?= $(STD) -pedantic -O3 -g -Wall -Werror -Wextra -Wformat=2 -Wshadow \
-Wno-long-long -Wno-overlength-strings -Wno-format-nonliteral -Wcast-align \
-Wwrite-strings -Wstrict-prototypes -Wold-style-definition -Wredundant-decls \
-Wnested-externs -Wmissing-include-dirs -Wswitch-default
@@ -10,15 +13,59 @@ TESTS = $(wildcard tests/*.c)
EXAMPLES = $(wildcard examples/*.c)
EXAMPLESEXE = $(EXAMPLES:.c=)
.PHONY: all check clean libs $(DIST)/$(PROJ).pc
all: $(EXAMPLESEXE) check
check: $(TESTS) mpc.c
$(CC) $(filter-out -Werror, $(CFLAGS)) $^ -lm -o test
./test
$(DIST):
$(MKDIR) $(DIST)/examples
examples/%: examples/%.c mpc.c
$(CC) $(CFLAGS) $^ -lm -o $@
check: $(DIST)/test-file $(DIST)/test-static $(DIST)/test-dynamic
./$(DIST)/test-file
./$(DIST)/test-static
LD_LIBRARY_PATH=$(DIST) ./$(DIST)/test-dynamic
$(DIST)/test-file: $(TESTS) $(PROJ).c $(PROJ).h tests/ptest.h
$(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) $(PROJ).c -lm -o $(DIST)/test-file
$(DIST)/test-dynamic: $(TESTS) $(DIST)/lib$(PROJ).so $(PROJ).h tests/ptest.h
$(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) -lm -L$(DIST) -l$(PROJ) -o $(DIST)/test-dynamic
$(DIST)/test-static: $(TESTS) $(DIST)/lib$(PROJ).a $(PROJ).h tests/ptest.h
$(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) -lm -L$(DIST) -l$(PROJ) -static -o $(DIST)/test-static
examples/%: $(DIST) examples/%.c $(PROJ).c $(PROJ).h
$(CC) $(CFLAGS) $(filter-out $(DIST) $(PROJ).h, $^) -lm -o $(DIST)/$@
$(DIST)/lib$(PROJ).so: $(PROJ).c $(PROJ).h
ifneq ($(OS),Windows_NT)
$(CC) $(CFLAGS) -fPIC -shared $(PROJ).c -o $(DIST)/lib$(PROJ).so
else
$(CC) $(CFLAGS) -shared $(PROJ).c -o $(DIST)/lib$(PROJ).so
endif
$(DIST)/lib$(PROJ).a: $(PROJ).c $(PROJ).h
$(CC) $(CFLAGS) -c $(PROJ).c -o $(DIST)/$(PROJ).o
$(AR) rcs $(DIST)/lib$(PROJ).a $(DIST)/$(PROJ).o
libs: $(DIST)/lib$(PROJ).so $(DIST)/lib$(PROJ).a
$(DIST)/$(PROJ).pc: $(DIST) $(PROJ).pc
cp $(PROJ).pc $(DIST)/$(PROJ).pc
sed -i '1i\prefix=$(PREFIX)/' $(DIST)/$(PROJ).pc
clean:
rm -rf test examples/doge examples/lispy examples/maths examples/smallc \
examples/foobar examples/tree_traversal
rm -rf -- $(DIST)
install: all
install -d -m644 $(DESTDIR)$(PREFIX)/{include,lib/pkgconfig,share/$(PROJ)}
install -m755 -t $(DESTDIR)$(PREFIX)/lib $(DIST)/lib*
install -m644 -t $(DESTDIR)$(PREFIX)/share/$(PROJ) $(PROJ).{c,h}
install -m644 $(PROJ).h $(DESTDIR)$(PREFIX)/include/$(PROJ).h
install -m644 $(DIST)/$(PROJ).pc $(DESTDIR)$(PREFIX)/lib/pkgconfig/$(PROJ).pc
uninstall:
rm -rf -- \
$(DESTDIR)$(PREFIX)/include/$(PROJ).h \
$(DESTDIR)$(PREFIX)/share/$(PROJ)/$(PROJ).{c,h} \
$(DESTDIR)$(PREFIX)/lib/lib$(PROJ).{so,a}

View File

@@ -1,7 +1,7 @@
Micro Parser Combinators
========================
Version 0.8.8
Version 0.9.0
About
@@ -312,13 +312,13 @@ Returns a parser that applies function `f` (optionality taking extra input `x`)
* * *
```c
mpc_parser_t *mpc_check(mpc_parser_t *a, mpc_check_t f, const char *e);
mpc_parser_t *mpc_check_with(mpc_parser_t *a, mpc_check_with_t f, void *x, const char *e);
mpc_parser_t *mpc_checkf(mpc_parser_t *a, mpc_check_t f, const char *fmt, ...);
mpc_parser_t *mpc_check_withf(mpc_parser_t *a, mpc_check_with_t f, void *x, const char *fmt, ...);
mpc_parser_t *mpc_check(mpc_parser_t *a, mpc_dtor_t da, mpc_check_t f, const char *e);
mpc_parser_t *mpc_check_with(mpc_parser_t *a, mpc_dtor_t da, mpc_check_with_t f, void *x, const char *e);
mpc_parser_t *mpc_checkf(mpc_parser_t *a, mpc_dtor_t da, mpc_check_t f, const char *fmt, ...);
mpc_parser_t *mpc_check_withf(mpc_parser_t *a, mpc_dtor_t da, mpc_check_with_t f, void *x, const char *fmt, ...);
```
Returns a parser that applies function `f` (optionally taking extra input `x`) to the result of parser `a`. If `f` returns non-zero, then the parser succeeds and returns the value of `a` (possibly modified by `f`). If `f` returns zero, then the parser fails with message `e`.
Returns a parser that applies function `f` (optionally taking extra input `x`) to the result of parser `a`. If `f` returns non-zero, then the parser succeeds and returns the value of `a` (possibly modified by `f`). If `f` returns zero, then the parser fails with message `e`, and the result of `a` is destroyed with the destructor `da`.
* * *
@@ -781,6 +781,8 @@ The syntax for this is defined as follows.
<tr><td><code>'a' | 'b'</code></td><td>Either <code>'a'</code> is required, or <code>'b'</code> is required.</td></tr>
<tr><td><code>'a'*</code></td><td>Zero or more <code>'a'</code> are required.</td></tr>
<tr><td><code>'a'+</code></td><td>One or more <code>'a'</code> are required.</td></tr>
<tr><td><code>'a'?</code></td><td>Zero or one <code>'a'</code> is required.</td></tr>
<tr><td><code>'a'{x}</code></td><td>Exactly <code>x</code> (integer) copies of <code>'a'</code> are required.</td></tr>
<tr><td><code>&lt;abba&gt;</code></td><td>The rule called <code>abba</code> is required.</td></tr>
</table>
@@ -991,5 +993,3 @@ When parsing from a grammar, the abstract syntax tree is tagged with different t
If you have a rule in your grammar called `string`, `char` or `regex`, you may encounter some confusion. This is because nodes will be tagged with (for example) `string` _either_ if they are a string primitive, _or_ if they were parsed via your `string` rule. If you are detecting node type using something like `strstr`, in this situation it might break. One solution to this is to always check that `string` is the innermost tag to test for string primitives, or to rename your rule called `string` to something that doesn't conflict.
Yes it is annoying but its probably not going to change!

105
mpc.c
View File

@@ -320,6 +320,7 @@ static void mpc_input_mark(mpc_input_t *i) {
}
static void mpc_input_unmark(mpc_input_t *i) {
int j;
if (i->backtrack < 1) { return; }
@@ -335,6 +336,9 @@ static void mpc_input_unmark(mpc_input_t *i) {
}
if (i->type == MPC_INPUT_PIPE && i->marks_num == 0) {
for (j = strlen(i->buffer) - 1; j >= 0; j--)
ungetc(i->buffer[j], i->file);
free(i->buffer);
i->buffer = NULL;
}
@@ -637,7 +641,7 @@ char *mpc_err_string(mpc_err_t *x) {
}
mpc_err_string_cat(buffer, &pos, &max,
"%s:%i:%i: error: expected ", x->filename, x->state.row+1, x->state.col+1);
"%s:%li:%li: error: expected ", x->filename, x->state.row+1, x->state.col+1);
if (x->expected_num == 0) { mpc_err_string_cat(buffer, &pos, &max, "ERROR: NOTHING EXPECTED"); }
if (x->expected_num == 1) { mpc_err_string_cat(buffer, &pos, &max, "%s", x->expected[0]); }
@@ -653,7 +657,7 @@ char *mpc_err_string(mpc_err_t *x) {
}
mpc_err_string_cat(buffer, &pos, &max, " at ");
mpc_err_string_cat(buffer, &pos, &max, mpc_err_char_unescape(x->recieved));
mpc_err_string_cat(buffer, &pos, &max, mpc_err_char_unescape(x->received));
mpc_err_string_cat(buffer, &pos, &max, "\n");
return realloc(buffer, strlen(buffer) + 1);
@@ -671,7 +675,7 @@ static mpc_err_t *mpc_err_new(mpc_input_t *i, const char *expected) {
x->expected[0] = mpc_malloc(i, strlen(expected) + 1);
strcpy(x->expected[0], expected);
x->failure = NULL;
x->recieved = mpc_input_peekc(i);
x->received = mpc_input_peekc(i);
return x;
}
@@ -686,7 +690,7 @@ static mpc_err_t *mpc_err_fail(mpc_input_t *i, const char *failure) {
x->expected = NULL;
x->failure = mpc_malloc(i, strlen(failure) + 1);
strcpy(x->failure, failure);
x->recieved = ' ';
x->received = ' ';
return x;
}
@@ -700,7 +704,7 @@ static mpc_err_t *mpc_err_file(const char *filename, const char *failure) {
x->expected = NULL;
x->failure = malloc(strlen(failure) + 1);
strcpy(x->failure, failure);
x->recieved = ' ';
x->received = ' ';
return x;
}
@@ -777,7 +781,7 @@ static mpc_err_t *mpc_err_or(mpc_input_t *i, mpc_err_t** x, int n) {
break;
}
e->recieved = x[j]->recieved;
e->received = x[j]->received;
for (k = 0; k < x[j]->expected_num; k++) {
if (!mpc_err_contains_expected(i, e, x[j]->expected[k])) {
@@ -923,8 +927,8 @@ typedef struct { int(*f)(char); } mpc_pdata_satisfy_t;
typedef struct { char *x; } mpc_pdata_string_t;
typedef struct { mpc_parser_t *x; mpc_apply_t f; } mpc_pdata_apply_t;
typedef struct { mpc_parser_t *x; mpc_apply_to_t f; void *d; } mpc_pdata_apply_to_t;
typedef struct { mpc_parser_t *x; mpc_check_t f; char *e; } mpc_pdata_check_t;
typedef struct { mpc_parser_t *x; mpc_check_with_t f; void *d; char *e; } mpc_pdata_check_with_t;
typedef struct { mpc_parser_t *x; mpc_dtor_t dx; mpc_check_t f; char *e; } mpc_pdata_check_t;
typedef struct { mpc_parser_t *x; mpc_dtor_t dx; mpc_check_with_t f; void *d; char *e; } mpc_pdata_check_with_t;
typedef struct { mpc_parser_t *x; } mpc_pdata_predict_t;
typedef struct { mpc_parser_t *x; mpc_dtor_t dx; mpc_ctor_t lf; } mpc_pdata_not_t;
typedef struct { int n; mpc_fold_t f; mpc_parser_t *x; mpc_dtor_t dx; } mpc_pdata_repeat_t;
@@ -1038,13 +1042,20 @@ enum {
if (x) { MPC_SUCCESS(r->output); } \
else { MPC_FAILURE(NULL); }
static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_err_t **e) {
#define MPC_MAX_RECURSION_DEPTH 1000
static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_err_t **e, int depth) {
int j = 0, k = 0;
mpc_result_t results_stk[MPC_PARSE_STACK_MIN];
mpc_result_t *results;
int results_slots = MPC_PARSE_STACK_MIN;
if (depth == MPC_MAX_RECURSION_DEPTH)
{
MPC_FAILURE(mpc_err_fail(i, "Maximum recursion depth exceeded!"));
}
switch (p->type) {
/* Basic Parsers */
@@ -1072,24 +1083,25 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e
/* Application Parsers */
case MPC_TYPE_APPLY:
if (mpc_parse_run(i, p->data.apply.x, r, e)) {
if (mpc_parse_run(i, p->data.apply.x, r, e, depth+1)) {
MPC_SUCCESS(mpc_parse_apply(i, p->data.apply.f, r->output));
} else {
MPC_FAILURE(r->output);
}
case MPC_TYPE_APPLY_TO:
if (mpc_parse_run(i, p->data.apply_to.x, r, e)) {
if (mpc_parse_run(i, p->data.apply_to.x, r, e, depth+1)) {
MPC_SUCCESS(mpc_parse_apply_to(i, p->data.apply_to.f, r->output, p->data.apply_to.d));
} else {
MPC_FAILURE(r->error);
}
case MPC_TYPE_CHECK:
if (mpc_parse_run(i, p->data.check.x, r, e)) {
if (mpc_parse_run(i, p->data.check.x, r, e, depth+1)) {
if (p->data.check.f(&r->output)) {
MPC_SUCCESS(r->output);
} else {
mpc_parse_dtor(i, p->data.check.dx, r->output);
MPC_FAILURE(mpc_err_fail(i, p->data.check.e));
}
} else {
@@ -1097,10 +1109,11 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e
}
case MPC_TYPE_CHECK_WITH:
if (mpc_parse_run(i, p->data.check_with.x, r, e)) {
if (mpc_parse_run(i, p->data.check_with.x, r, e, depth+1)) {
if (p->data.check_with.f(&r->output, p->data.check_with.d)) {
MPC_SUCCESS(r->output);
} else {
mpc_parse_dtor(i, p->data.check.dx, r->output);
MPC_FAILURE(mpc_err_fail(i, p->data.check_with.e));
}
} else {
@@ -1109,7 +1122,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e
case MPC_TYPE_EXPECT:
mpc_input_suppress_enable(i);
if (mpc_parse_run(i, p->data.expect.x, r, e)) {
if (mpc_parse_run(i, p->data.expect.x, r, e, depth+1)) {
mpc_input_suppress_disable(i);
MPC_SUCCESS(r->output);
} else {
@@ -1119,7 +1132,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e
case MPC_TYPE_PREDICT:
mpc_input_backtrack_disable(i);
if (mpc_parse_run(i, p->data.predict.x, r, e)) {
if (mpc_parse_run(i, p->data.predict.x, r, e, depth+1)) {
mpc_input_backtrack_enable(i);
MPC_SUCCESS(r->output);
} else {
@@ -1134,7 +1147,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e
case MPC_TYPE_NOT:
mpc_input_mark(i);
mpc_input_suppress_enable(i);
if (mpc_parse_run(i, p->data.not.x, r, e)) {
if (mpc_parse_run(i, p->data.not.x, r, e, depth+1)) {
mpc_input_rewind(i);
mpc_input_suppress_disable(i);
mpc_parse_dtor(i, p->data.not.dx, r->output);
@@ -1146,7 +1159,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e
}
case MPC_TYPE_MAYBE:
if (mpc_parse_run(i, p->data.not.x, r, e)) {
if (mpc_parse_run(i, p->data.not.x, r, e, depth+1)) {
MPC_SUCCESS(r->output);
} else {
*e = mpc_err_merge(i, *e, r->error);
@@ -1159,7 +1172,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e
results = results_stk;
while (mpc_parse_run(i, p->data.repeat.x, &results[j], e)) {
while (mpc_parse_run(i, p->data.repeat.x, &results[j], e, depth+1)) {
j++;
if (j == MPC_PARSE_STACK_MIN) {
results_slots = j + j / 2;
@@ -1181,7 +1194,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e
results = results_stk;
while (mpc_parse_run(i, p->data.repeat.x, &results[j], e)) {
while (mpc_parse_run(i, p->data.repeat.x, &results[j], e, depth+1)) {
j++;
if (j == MPC_PARSE_STACK_MIN) {
results_slots = j + j / 2;
@@ -1212,7 +1225,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e
? mpc_malloc(i, sizeof(mpc_result_t) * p->data.repeat.n)
: results_stk;
while (mpc_parse_run(i, p->data.repeat.x, &results[j], e)) {
while (mpc_parse_run(i, p->data.repeat.x, &results[j], e, depth+1)) {
j++;
if (j == p->data.repeat.n) { break; }
}
@@ -1241,7 +1254,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e
: results_stk;
for (j = 0; j < p->data.or.n; j++) {
if (mpc_parse_run(i, p->data.or.xs[j], &results[j], e)) {
if (mpc_parse_run(i, p->data.or.xs[j], &results[j], e, depth+1)) {
MPC_SUCCESS(results[j].output;
if (p->data.or.n > MPC_PARSE_STACK_MIN) { mpc_free(i, results); });
} else {
@@ -1262,7 +1275,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e
mpc_input_mark(i);
for (j = 0; j < p->data.and.n; j++) {
if (!mpc_parse_run(i, p->data.and.xs[j], &results[j], e)) {
if (!mpc_parse_run(i, p->data.and.xs[j], &results[j], e, depth+1)) {
mpc_input_rewind(i);
for (k = 0; k < j; k++) {
mpc_parse_dtor(i, p->data.and.dxs[k], results[k].output);
@@ -1295,7 +1308,7 @@ int mpc_parse_input(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r) {
int x;
mpc_err_t *e = mpc_err_fail(i, "Unknown Error");
e->state = mpc_state_invalid();
x = mpc_parse_run(i, p, r, &e);
x = mpc_parse_run(i, p, r, &e, 0);
if (x) {
mpc_err_delete_internal(i, e);
r->output = mpc_export(i, r->output);
@@ -1799,20 +1812,22 @@ mpc_parser_t *mpc_apply_to(mpc_parser_t *a, mpc_apply_to_t f, void *x) {
return p;
}
mpc_parser_t *mpc_check(mpc_parser_t *a, mpc_check_t f, const char *e) {
mpc_parser_t *mpc_check(mpc_parser_t *a, mpc_dtor_t da, mpc_check_t f, const char *e) {
mpc_parser_t *p = mpc_undefined();
p->type = MPC_TYPE_CHECK;
p->data.check.x = a;
p->data.check.f = f;
p->data.check.e = malloc(strlen(e) + 1);
p->type = MPC_TYPE_CHECK;
p->data.check.x = a;
p->data.check.dx = da;
p->data.check.f = f;
p->data.check.e = malloc(strlen(e) + 1);
strcpy(p->data.check.e, e);
return p;
}
mpc_parser_t *mpc_check_with(mpc_parser_t *a, mpc_check_with_t f, void *x, const char *e) {
mpc_parser_t *p = mpc_undefined();
p->type = MPC_TYPE_CHECK_WITH;
mpc_parser_t *mpc_check_with(mpc_parser_t *a, mpc_dtor_t da, mpc_check_with_t f, void *x, const char *e) {
mpc_parser_t *p = mpc_undefined();
p->type = MPC_TYPE_CHECK_WITH;
p->data.check_with.x = a;
p->data.check_with.dx = da;
p->data.check_with.f = f;
p->data.check_with.d = x;
p->data.check_with.e = malloc(strlen(e) + 1);
@@ -1820,34 +1835,34 @@ mpc_parser_t *mpc_check_with(mpc_parser_t *a, mpc_check_with_t f, void *x, const
return p;
}
mpc_parser_t *mpc_checkf(mpc_parser_t *a, mpc_check_t f, const char *fmt, ...) {
va_list va;
char *buffer;
mpc_parser_t *p;
mpc_parser_t *mpc_checkf(mpc_parser_t *a, mpc_dtor_t da, mpc_check_t f, const char *fmt, ...) {
va_list va;
char *buffer;
mpc_parser_t *p;
va_start(va, fmt);
buffer = malloc(2048);
vsprintf(buffer, fmt, va);
va_end(va);
p = mpc_check (a, f, buffer);
free (buffer);
p = mpc_check(a, da, f, buffer);
free(buffer);
return p;
}
mpc_parser_t *mpc_check_withf(mpc_parser_t *a, mpc_check_with_t f, void *x, const char *fmt, ...) {
va_list va;
char *buffer;
mpc_parser_t *p;
mpc_parser_t *mpc_check_withf(mpc_parser_t *a, mpc_dtor_t da, mpc_check_with_t f, void *x, const char *fmt, ...) {
va_list va;
char *buffer;
mpc_parser_t *p;
va_start(va, fmt);
buffer = malloc(2048);
vsprintf(buffer, fmt, va);
va_end(va);
p = mpc_check_with (a, f, x, buffer);
free (buffer);
p = mpc_check_with(a, da, f, x, buffer);
free(buffer);
return p;
}
@@ -2446,7 +2461,7 @@ mpc_val_t *mpcf_float(mpc_val_t *x) {
mpc_val_t *mpcf_strtriml(mpc_val_t *x) {
char *s = x;
while (isspace(*s)) {
while (isspace((unsigned char)*s)) {
memmove(s, s+1, strlen(s));
}
return s;
@@ -2455,7 +2470,7 @@ mpc_val_t *mpcf_strtriml(mpc_val_t *x) {
mpc_val_t *mpcf_strtrimr(mpc_val_t *x) {
char *s = x;
size_t l = strlen(s);
while (isspace(s[l-1])) {
while (l > 0 && isspace((unsigned char)s[l-1])) {
s[l-1] = '\0'; l--;
}
return s;

11
mpc.h
View File

@@ -43,7 +43,7 @@ typedef struct {
char *filename;
char *failure;
char **expected;
char recieved;
char received;
} mpc_err_t;
void mpc_err_delete(mpc_err_t *e);
@@ -129,10 +129,10 @@ mpc_parser_t *mpc_expect(mpc_parser_t *a, const char *e);
mpc_parser_t *mpc_expectf(mpc_parser_t *a, const char *fmt, ...);
mpc_parser_t *mpc_apply(mpc_parser_t *a, mpc_apply_t f);
mpc_parser_t *mpc_apply_to(mpc_parser_t *a, mpc_apply_to_t f, void *x);
mpc_parser_t *mpc_check(mpc_parser_t *a, mpc_check_t f, const char *e);
mpc_parser_t *mpc_check_with(mpc_parser_t *a, mpc_check_with_t f, void *x, const char *e);
mpc_parser_t *mpc_checkf(mpc_parser_t *a, mpc_check_t f, const char *fmt, ...);
mpc_parser_t *mpc_check_withf(mpc_parser_t *a, mpc_check_with_t f, void *x, const char *fmt, ...);
mpc_parser_t *mpc_check(mpc_parser_t *a, mpc_dtor_t da, mpc_check_t f, const char *e);
mpc_parser_t *mpc_check_with(mpc_parser_t *a, mpc_dtor_t da, mpc_check_with_t f, void *x, const char *e);
mpc_parser_t *mpc_checkf(mpc_parser_t *a, mpc_dtor_t da, mpc_check_t f, const char *fmt, ...);
mpc_parser_t *mpc_check_withf(mpc_parser_t *a, mpc_dtor_t da, mpc_check_with_t f, void *x, const char *fmt, ...);
mpc_parser_t *mpc_not(mpc_parser_t *a, mpc_dtor_t da);
mpc_parser_t *mpc_not_lift(mpc_parser_t *a, mpc_dtor_t da, mpc_ctor_t lf);
@@ -258,6 +258,7 @@ 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_freefold(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);

8
mpc.pc Normal file
View File

@@ -0,0 +1,8 @@
libdir=${prefix}/lib
includedir=${prefix}/include
Name: mpc
Description: Library for creating parser combinators
Version: 0.9.0
Libs: -L${libdir} -lmpc
Cflags: -I${includedir}

View File

@@ -12,7 +12,7 @@ static int check_is(mpc_val_t** x, void* t) {
void test_check(void) {
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'");
mpc_parser_t* p = mpc_check(mpc_or(2, mpc_char('a'), mpc_char('b')), free, check_is_a, "Expected 'a'");
success = mpc_parse("test", "a", p, &r);
PT_ASSERT(success);
@@ -30,7 +30,7 @@ void test_check(void) {
void test_check_with(void) {
int success;
mpc_result_t r;
mpc_parser_t* p = mpc_check_with(mpc_or(2, mpc_char('a'), mpc_char('b')), check_is, (void*)"a", "Expected 'a'");
mpc_parser_t* p = mpc_check_with(mpc_or(2, mpc_char('a'), mpc_char('b')), free, check_is, (void*)"a", "Expected 'a'");
success = mpc_parse("test", "a", p, &r);
PT_ASSERT(success);
@@ -48,7 +48,7 @@ void test_check_with(void) {
void test_checkf(void) {
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");
mpc_parser_t* p = mpc_checkf(mpc_or(2, mpc_char('a'), mpc_char('b')), free, check_is_a, "Expected '%s'", "a");
success = mpc_parse("test", "a", p, &r);
PT_ASSERT(success);
@@ -66,7 +66,7 @@ void test_checkf(void) {
void test_check_withf(void) {
int success;
mpc_result_t r;
mpc_parser_t* p = mpc_check_withf(mpc_or(2, mpc_char('a'), mpc_char('b')), check_is, (void*)"a", "Expected '%s'", "a");
mpc_parser_t* p = mpc_check_withf(mpc_or(2, mpc_char('a'), mpc_char('b')), free, check_is, (void*)"a", "Expected '%s'", "a");
success = mpc_parse("test", "a", p, &r);
PT_ASSERT(success);