Switched parsing to use C function stack
This commit is contained in:
478
mpc.c
478
mpc.c
@@ -748,225 +748,6 @@ struct mpc_parser_t {
|
|||||||
mpc_pdata_t data;
|
mpc_pdata_t data;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
** Stack Type
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
|
|
||||||
int parsers_num;
|
|
||||||
int parsers_slots;
|
|
||||||
mpc_parser_t **parsers;
|
|
||||||
int *states;
|
|
||||||
|
|
||||||
int results_num;
|
|
||||||
int results_slots;
|
|
||||||
mpc_result_t *results;
|
|
||||||
int *returns;
|
|
||||||
|
|
||||||
mpc_err_t *err;
|
|
||||||
|
|
||||||
} mpc_stack_t;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
MPC_STACK_MIN = 256
|
|
||||||
};
|
|
||||||
|
|
||||||
static mpc_stack_t *mpc_stack_new(const char *filename) {
|
|
||||||
mpc_stack_t *s = malloc(sizeof(mpc_stack_t));
|
|
||||||
|
|
||||||
s->parsers_num = 0;
|
|
||||||
s->parsers_slots = MPC_STACK_MIN;
|
|
||||||
s->parsers = malloc(sizeof(mpc_parser_t*) * MPC_STACK_MIN);
|
|
||||||
s->states = malloc(sizeof(int) * MPC_STACK_MIN);
|
|
||||||
|
|
||||||
s->results_num = 0;
|
|
||||||
s->results_slots = MPC_STACK_MIN;
|
|
||||||
|
|
||||||
s->results = malloc(sizeof(mpc_result_t) * MPC_STACK_MIN);
|
|
||||||
s->returns = malloc(sizeof(int) * MPC_STACK_MIN);
|
|
||||||
|
|
||||||
s->err = mpc_err_fail(filename, mpc_state_invalid(), "Unknown Error");
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mpc_stack_err(mpc_stack_t *s, mpc_err_t* e) {
|
|
||||||
mpc_err_t *errs[2];
|
|
||||||
errs[0] = s->err;
|
|
||||||
errs[1] = e;
|
|
||||||
s->err = mpc_err_or(errs, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mpc_stack_terminate(mpc_stack_t *s, mpc_result_t *r) {
|
|
||||||
int success = s->returns[0];
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
r->output = s->results[0].output;
|
|
||||||
mpc_err_delete(s->err);
|
|
||||||
} else {
|
|
||||||
mpc_stack_err(s, s->results[0].error);
|
|
||||||
r->error = s->err;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(s->parsers);
|
|
||||||
free(s->states);
|
|
||||||
free(s->results);
|
|
||||||
free(s->returns);
|
|
||||||
free(s);
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Stack Parser Stuff */
|
|
||||||
|
|
||||||
static void mpc_stack_set_state(mpc_stack_t *s, int x) {
|
|
||||||
s->states[s->parsers_num-1] = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mpc_stack_parsers_reserve_more(mpc_stack_t *s) {
|
|
||||||
if (s->parsers_num > s->parsers_slots) {
|
|
||||||
s->parsers_slots = s->parsers_num + s->parsers_num / 2;
|
|
||||||
s->parsers = realloc(s->parsers, sizeof(mpc_parser_t*) * s->parsers_slots);
|
|
||||||
s->states = realloc(s->states, sizeof(int) * s->parsers_slots);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mpc_stack_parsers_reserve_less(mpc_stack_t *s) {
|
|
||||||
if (s->parsers_slots > s->parsers_num + s->parsers_num / 2
|
|
||||||
&& s->parsers_slots > MPC_STACK_MIN) {
|
|
||||||
s->parsers_slots =
|
|
||||||
s->parsers_num > MPC_STACK_MIN ?
|
|
||||||
s->parsers_num : MPC_STACK_MIN;
|
|
||||||
s->parsers = realloc(s->parsers, sizeof(mpc_parser_t*) * s->parsers_slots);
|
|
||||||
s->states = realloc(s->states, sizeof(int) * s->parsers_slots);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mpc_stack_pushp(mpc_stack_t *s, mpc_parser_t *p) {
|
|
||||||
s->parsers_num++;
|
|
||||||
mpc_stack_parsers_reserve_more(s);
|
|
||||||
s->parsers[s->parsers_num-1] = p;
|
|
||||||
s->states[s->parsers_num-1] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mpc_stack_popp(mpc_stack_t *s, mpc_parser_t **p, int *st) {
|
|
||||||
*p = s->parsers[s->parsers_num-1];
|
|
||||||
*st = s->states[s->parsers_num-1];
|
|
||||||
s->parsers_num--;
|
|
||||||
mpc_stack_parsers_reserve_less(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mpc_stack_peepp(mpc_stack_t *s, mpc_parser_t **p, int *st) {
|
|
||||||
*p = s->parsers[s->parsers_num-1];
|
|
||||||
*st = s->states[s->parsers_num-1];
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mpc_stack_empty(mpc_stack_t *s) {
|
|
||||||
return s->parsers_num == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Stack Result Stuff */
|
|
||||||
|
|
||||||
static mpc_result_t mpc_result_err(mpc_err_t *e) {
|
|
||||||
mpc_result_t r;
|
|
||||||
r.error = e;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static mpc_result_t mpc_result_out(mpc_val_t *x) {
|
|
||||||
mpc_result_t r;
|
|
||||||
r.output = x;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mpc_stack_results_reserve_more(mpc_stack_t *s) {
|
|
||||||
if (s->results_num > s->results_slots) {
|
|
||||||
s->results_slots = s->results_num + s->results_num / 2;
|
|
||||||
s->results = realloc(s->results, sizeof(mpc_result_t) * s->results_slots);
|
|
||||||
s->returns = realloc(s->returns, sizeof(int) * s->results_slots);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mpc_stack_results_reserve_less(mpc_stack_t *s) {
|
|
||||||
if (s->results_slots > s->results_num + s->results_num / 2
|
|
||||||
&& s->results_slots > MPC_STACK_MIN) {
|
|
||||||
s->results_slots =
|
|
||||||
s->results_num > MPC_STACK_MIN ?
|
|
||||||
s->results_num : MPC_STACK_MIN;
|
|
||||||
s->results = realloc(s->results, sizeof(mpc_result_t) * s->results_slots);
|
|
||||||
s->returns = realloc(s->returns, sizeof(int) * s->results_slots);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mpc_stack_pushr(mpc_stack_t *s, mpc_result_t x, int r) {
|
|
||||||
s->results_num++;
|
|
||||||
mpc_stack_results_reserve_more(s);
|
|
||||||
s->results[s->results_num-1] = x;
|
|
||||||
s->returns[s->results_num-1] = r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mpc_stack_popr(mpc_stack_t *s, mpc_result_t *x) {
|
|
||||||
int r;
|
|
||||||
*x = s->results[s->results_num-1];
|
|
||||||
r = s->returns[s->results_num-1];
|
|
||||||
s->results_num--;
|
|
||||||
mpc_stack_results_reserve_less(s);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mpc_stack_peekr(mpc_stack_t *s, mpc_result_t *x) {
|
|
||||||
*x = s->results[s->results_num-1];
|
|
||||||
return s->returns[s->results_num-1];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mpc_stack_popr_err(mpc_stack_t *s, int n) {
|
|
||||||
mpc_result_t x;
|
|
||||||
while (n) {
|
|
||||||
mpc_stack_popr(s, &x);
|
|
||||||
mpc_stack_err(s, x.error);
|
|
||||||
n--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mpc_stack_popr_out(mpc_stack_t *s, int n, mpc_dtor_t *ds) {
|
|
||||||
mpc_result_t x;
|
|
||||||
while (n) {
|
|
||||||
mpc_stack_popr(s, &x);
|
|
||||||
ds[n-1](x.output);
|
|
||||||
n--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mpc_stack_popr_out_single(mpc_stack_t *s, int n, mpc_dtor_t dx) {
|
|
||||||
mpc_result_t x;
|
|
||||||
while (n) {
|
|
||||||
mpc_stack_popr(s, &x);
|
|
||||||
dx(x.output);
|
|
||||||
n--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mpc_stack_popr_n(mpc_stack_t *s, int n) {
|
|
||||||
mpc_result_t x;
|
|
||||||
while (n) {
|
|
||||||
mpc_stack_popr(s, &x);
|
|
||||||
n--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static mpc_val_t *mpc_stack_merger_out(mpc_stack_t *s, int n, mpc_fold_t f) {
|
|
||||||
mpc_val_t *x = f(n, (mpc_val_t**)(&s->results[s->results_num-n]));
|
|
||||||
mpc_stack_popr_n(s, n);
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
static mpc_err_t *mpc_stack_merger_err(mpc_stack_t *s, int n) {
|
|
||||||
mpc_err_t *x = mpc_err_or((mpc_err_t**)(&s->results[s->results_num-n]), n);
|
|
||||||
mpc_stack_popr_n(s, n);
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This is rather pleasant. The core parsing routine
|
** This is rather pleasant. The core parsing routine
|
||||||
** is written in about 200 lines of C.
|
** is written in about 200 lines of C.
|
||||||
@@ -977,51 +758,36 @@ static mpc_err_t *mpc_stack_merger_err(mpc_stack_t *s, int n) {
|
|||||||
** Particularly nice are the `or` and `and`
|
** Particularly nice are the `or` and `and`
|
||||||
** types which have a broken but mirrored structure
|
** types which have a broken but mirrored structure
|
||||||
** with return value and error reflected.
|
** with return value and error reflected.
|
||||||
**
|
|
||||||
** When this function was written in recursive form
|
|
||||||
** it looked pretty nice. But I've since switched
|
|
||||||
** it around to an awkward while loop. It was an
|
|
||||||
** unfortunate change for code simplicity but it
|
|
||||||
** is noble in the name of performance (and
|
|
||||||
** not smashing the stack).
|
|
||||||
**
|
|
||||||
** But it is now a pretty ugly beast...
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MPC_CONTINUE(st, x) mpc_stack_set_state(stk, st); mpc_stack_pushp(stk, x); continue
|
#define MPC_SUCCESS(x) r->output = x; return 1
|
||||||
#define MPC_SUCCESS(x) mpc_stack_popp(stk, &p, &st); mpc_stack_pushr(stk, mpc_result_out(x), 1); continue
|
#define MPC_FAILURE(x) r->error = x; return 0
|
||||||
#define MPC_FAILURE(x) mpc_stack_popp(stk, &p, &st); mpc_stack_pushr(stk, mpc_result_err(x), 0); continue
|
#define MPC_PRIMITIVE(x) \
|
||||||
#define MPC_PRIMITIVE(x, f) if (f) { MPC_SUCCESS(x); } else { MPC_FAILURE(mpc_err_fail(i->filename, i->state, "Incorrect Input")); }
|
if (x) { MPC_SUCCESS(r->output); } \
|
||||||
|
else { MPC_FAILURE(mpc_err_fail(i->filename, i->state, "Incorrect Input")); }
|
||||||
|
|
||||||
int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) {
|
enum {
|
||||||
|
MPC_PARSE_STACK_MIN = 8
|
||||||
|
};
|
||||||
|
|
||||||
/* Stack */
|
int mpc_parse_input(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r) {
|
||||||
int st = 0;
|
|
||||||
mpc_parser_t *p = NULL;
|
|
||||||
mpc_stack_t *stk = mpc_stack_new(i->filename);
|
|
||||||
|
|
||||||
/* Variables */
|
int j = 0, k = 0;
|
||||||
char *s;
|
mpc_result_t results_stk[MPC_PARSE_STACK_MIN];
|
||||||
mpc_result_t r;
|
mpc_result_t *results;
|
||||||
|
int results_slots = MPC_PARSE_STACK_MIN;
|
||||||
/* Go! */
|
|
||||||
mpc_stack_pushp(stk, init);
|
|
||||||
|
|
||||||
while (!mpc_stack_empty(stk)) {
|
|
||||||
|
|
||||||
mpc_stack_peepp(stk, &p, &st);
|
|
||||||
|
|
||||||
switch (p->type) {
|
switch (p->type) {
|
||||||
|
|
||||||
/* Basic Parsers */
|
/* Basic Parsers */
|
||||||
|
|
||||||
case MPC_TYPE_ANY: MPC_PRIMITIVE(s, mpc_input_any(i, &s));
|
case MPC_TYPE_ANY: MPC_PRIMITIVE(mpc_input_any(i, (char**)&r->output));
|
||||||
case MPC_TYPE_SINGLE: MPC_PRIMITIVE(s, mpc_input_char(i, p->data.single.x, &s));
|
case MPC_TYPE_SINGLE: MPC_PRIMITIVE(mpc_input_char(i, p->data.single.x, (char**)&r->output));
|
||||||
case MPC_TYPE_RANGE: MPC_PRIMITIVE(s, mpc_input_range(i, p->data.range.x, p->data.range.y, &s));
|
case MPC_TYPE_RANGE: MPC_PRIMITIVE(mpc_input_range(i, p->data.range.x, p->data.range.y, (char**)&r->output));
|
||||||
case MPC_TYPE_ONEOF: MPC_PRIMITIVE(s, mpc_input_oneof(i, p->data.string.x, &s));
|
case MPC_TYPE_ONEOF: MPC_PRIMITIVE(mpc_input_oneof(i, p->data.string.x, (char**)&r->output));
|
||||||
case MPC_TYPE_NONEOF: MPC_PRIMITIVE(s, mpc_input_noneof(i, p->data.string.x, &s));
|
case MPC_TYPE_NONEOF: MPC_PRIMITIVE(mpc_input_noneof(i, p->data.string.x, (char**)&r->output));
|
||||||
case MPC_TYPE_SATISFY: MPC_PRIMITIVE(s, mpc_input_satisfy(i, p->data.satisfy.f, &s));
|
case MPC_TYPE_SATISFY: MPC_PRIMITIVE(mpc_input_satisfy(i, p->data.satisfy.f, (char**)&r->output));
|
||||||
case MPC_TYPE_STRING: MPC_PRIMITIVE(s, mpc_input_string(i, p->data.string.x, &s));
|
case MPC_TYPE_STRING: MPC_PRIMITIVE(mpc_input_string(i, p->data.string.x, (char**)&r->output));
|
||||||
|
|
||||||
/* Other parsers */
|
/* Other parsers */
|
||||||
|
|
||||||
@@ -1042,42 +808,35 @@ int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) {
|
|||||||
/* Application Parsers */
|
/* Application Parsers */
|
||||||
|
|
||||||
case MPC_TYPE_EXPECT:
|
case MPC_TYPE_EXPECT:
|
||||||
if (st == 0) { MPC_CONTINUE(1, p->data.expect.x); }
|
if (mpc_parse_input(i, p->data.expect.x, r)) {
|
||||||
if (st == 1) {
|
MPC_SUCCESS(r->output);
|
||||||
if (mpc_stack_popr(stk, &r)) {
|
|
||||||
MPC_SUCCESS(r.output);
|
|
||||||
} else {
|
} else {
|
||||||
mpc_err_delete(r.error);
|
mpc_err_delete(r->error);
|
||||||
MPC_FAILURE(mpc_err_new(i->filename, i->state, p->data.expect.m, mpc_input_peekc(i)));
|
MPC_FAILURE(mpc_err_new(i->filename, i->state, p->data.expect.m, mpc_input_peekc(i)));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
case MPC_TYPE_APPLY:
|
case MPC_TYPE_APPLY:
|
||||||
if (st == 0) { MPC_CONTINUE(1, p->data.apply.x); }
|
if (mpc_parse_input(i, p->data.apply.x, r)) {
|
||||||
if (st == 1) {
|
MPC_SUCCESS(p->data.apply.f(r->output));
|
||||||
if (mpc_stack_popr(stk, &r)) {
|
|
||||||
MPC_SUCCESS(p->data.apply.f(r.output));
|
|
||||||
} else {
|
} else {
|
||||||
MPC_FAILURE(r.error);
|
MPC_FAILURE(r->output);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case MPC_TYPE_APPLY_TO:
|
case MPC_TYPE_APPLY_TO:
|
||||||
if (st == 0) { MPC_CONTINUE(1, p->data.apply_to.x); }
|
if (mpc_parse_input(i, p->data.apply_to.x, r)) {
|
||||||
if (st == 1) {
|
MPC_SUCCESS(p->data.apply_to.f(r->output, p->data.apply_to.d));
|
||||||
if (mpc_stack_popr(stk, &r)) {
|
|
||||||
MPC_SUCCESS(p->data.apply_to.f(r.output, p->data.apply_to.d));
|
|
||||||
} else {
|
} else {
|
||||||
MPC_FAILURE(r.error);
|
MPC_FAILURE(r->error);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case MPC_TYPE_PREDICT:
|
case MPC_TYPE_PREDICT:
|
||||||
if (st == 0) { mpc_input_backtrack_disable(i); MPC_CONTINUE(1, p->data.predict.x); }
|
mpc_input_backtrack_disable(i);
|
||||||
if (st == 1) {
|
if (mpc_parse_input(i, p->data.predict.x, r)) {
|
||||||
mpc_input_backtrack_enable(i);
|
mpc_input_backtrack_enable(i);
|
||||||
mpc_stack_popp(stk, &p, &st);
|
MPC_SUCCESS(r->output);
|
||||||
continue;
|
} else {
|
||||||
|
mpc_input_backtrack_enable(i);
|
||||||
|
MPC_FAILURE(r->error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Optional Parsers */
|
/* Optional Parsers */
|
||||||
@@ -1085,77 +844,81 @@ int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) {
|
|||||||
/* TODO: Update Not Error Message */
|
/* TODO: Update Not Error Message */
|
||||||
|
|
||||||
case MPC_TYPE_NOT:
|
case MPC_TYPE_NOT:
|
||||||
if (st == 0) { mpc_input_mark(i); MPC_CONTINUE(1, p->data.not.x); }
|
mpc_input_mark(i);
|
||||||
if (st == 1) {
|
if (mpc_parse_input(i, p->data.not.x, r)) {
|
||||||
if (mpc_stack_popr(stk, &r)) {
|
|
||||||
mpc_input_rewind(i);
|
mpc_input_rewind(i);
|
||||||
p->data.not.dx(r.output);
|
p->data.not.dx(r->output);
|
||||||
MPC_FAILURE(mpc_err_new(i->filename, i->state, "opposite", mpc_input_peekc(i)));
|
MPC_FAILURE(mpc_err_new(i->filename, i->state, "opposite", mpc_input_peekc(i)));
|
||||||
} else {
|
} else {
|
||||||
mpc_input_unmark(i);
|
mpc_input_unmark(i);
|
||||||
mpc_stack_err(stk, r.error);
|
mpc_err_delete(r->error);
|
||||||
MPC_SUCCESS(p->data.not.lf());
|
MPC_SUCCESS(p->data.not.lf());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
case MPC_TYPE_MAYBE:
|
case MPC_TYPE_MAYBE:
|
||||||
if (st == 0) { MPC_CONTINUE(1, p->data.not.x); }
|
if (mpc_parse_input(i, p->data.not.x, r)) {
|
||||||
if (st == 1) {
|
MPC_SUCCESS(r->output);
|
||||||
if (mpc_stack_popr(stk, &r)) {
|
|
||||||
MPC_SUCCESS(r.output);
|
|
||||||
} else {
|
} else {
|
||||||
mpc_stack_err(stk, r.error);
|
mpc_err_delete(r->error);
|
||||||
MPC_SUCCESS(p->data.not.lf());
|
MPC_SUCCESS(p->data.not.lf());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Repeat Parsers */
|
/* Repeat Parsers */
|
||||||
|
|
||||||
case MPC_TYPE_MANY:
|
case MPC_TYPE_MANY:
|
||||||
if (st == 0) { MPC_CONTINUE(st+1, p->data.repeat.x); }
|
|
||||||
if (st > 0) {
|
results = malloc(sizeof(mpc_result_t) * results_slots);
|
||||||
if (mpc_stack_peekr(stk, &r)) {
|
|
||||||
MPC_CONTINUE(st+1, p->data.repeat.x);
|
while (mpc_parse_input(i, p->data.repeat.x, &results[j])) {
|
||||||
} else {
|
j++;
|
||||||
mpc_stack_popr(stk, &r);
|
if (j >= results_slots) {
|
||||||
mpc_stack_err(stk, r.error);
|
results_slots = j + j / 2;
|
||||||
MPC_SUCCESS(mpc_stack_merger_out(stk, st-1, p->data.repeat.f));
|
results = realloc(results, sizeof(mpc_result_t) * results_slots);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mpc_err_delete(results[j].error);
|
||||||
|
MPC_SUCCESS(p->data.repeat.f(j, (mpc_val_t**)results); free(results));
|
||||||
|
|
||||||
case MPC_TYPE_MANY1:
|
case MPC_TYPE_MANY1:
|
||||||
if (st == 0) { MPC_CONTINUE(st+1, p->data.repeat.x); }
|
|
||||||
if (st > 0) {
|
results = malloc(sizeof(mpc_result_t) * results_slots);
|
||||||
if (mpc_stack_peekr(stk, &r)) {
|
|
||||||
MPC_CONTINUE(st+1, p->data.repeat.x);
|
while (mpc_parse_input(i, p->data.repeat.x, &results[j])) {
|
||||||
} else {
|
j++;
|
||||||
if (st == 1) {
|
if (j >= results_slots) {
|
||||||
mpc_stack_popr(stk, &r);
|
results_slots = j + j / 2;
|
||||||
MPC_FAILURE(mpc_err_many1(r.error));
|
results = realloc(results, sizeof(mpc_result_t) * results_slots);
|
||||||
} else {
|
|
||||||
mpc_stack_popr(stk, &r);
|
|
||||||
mpc_stack_err(stk, r.error);
|
|
||||||
MPC_SUCCESS(mpc_stack_merger_out(stk, st-1, p->data.repeat.f));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (j == 0) {
|
||||||
|
MPC_FAILURE(mpc_err_many1(results[0].error); free(results));
|
||||||
|
} else {
|
||||||
|
mpc_err_delete(results[j].error);
|
||||||
|
MPC_SUCCESS(p->data.repeat.f(j, (mpc_val_t**)results); free(results));
|
||||||
}
|
}
|
||||||
|
|
||||||
case MPC_TYPE_COUNT:
|
case MPC_TYPE_COUNT:
|
||||||
if (st == 0) { mpc_input_mark(i); MPC_CONTINUE(st+1, p->data.repeat.x); }
|
|
||||||
if (st > 0) {
|
results = p->data.repeat.n > MPC_PARSE_STACK_MIN
|
||||||
if (!mpc_stack_peekr(stk, &r)) {
|
? malloc(sizeof(mpc_result_t) * p->data.repeat.n)
|
||||||
mpc_stack_popr(stk, &r);
|
: results_stk;
|
||||||
mpc_stack_popr_out_single(stk, st-1, p->data.repeat.dx);
|
|
||||||
mpc_input_rewind(i);
|
while (mpc_parse_input(i, p->data.repeat.x, &results[j])) {
|
||||||
MPC_FAILURE(mpc_err_count(r.error, p->data.repeat.n));
|
j++;
|
||||||
} else {
|
if (j == p->data.repeat.n) { break; }
|
||||||
if (st < p->data.repeat.n) {
|
|
||||||
MPC_CONTINUE(st+1, p->data.repeat.x);
|
|
||||||
} else {
|
|
||||||
mpc_input_unmark(i);
|
|
||||||
MPC_SUCCESS(mpc_stack_merger_out(stk, st, p->data.repeat.f));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (j == p->data.repeat.n) {
|
||||||
|
MPC_SUCCESS(p->data.repeat.f(j, (mpc_val_t**)results);
|
||||||
|
if (p->data.repeat.n > MPC_PARSE_STACK_MIN) { free(results); });
|
||||||
|
} else {
|
||||||
|
for (k = 0; k < j; k++) {
|
||||||
|
p->data.repeat.dx(results[k].output);
|
||||||
}
|
}
|
||||||
|
MPC_FAILURE(mpc_err_count(results[j].error, p->data.repeat.n);
|
||||||
|
if (p->data.repeat.n > MPC_PARSE_STACK_MIN) { free(results); });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Combinatory Parsers */
|
/* Combinatory Parsers */
|
||||||
@@ -1164,32 +927,46 @@ int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) {
|
|||||||
|
|
||||||
if (p->data.or.n == 0) { MPC_SUCCESS(NULL); }
|
if (p->data.or.n == 0) { MPC_SUCCESS(NULL); }
|
||||||
|
|
||||||
if (st == 0) { MPC_CONTINUE(st+1, p->data.or.xs[st]); }
|
results = p->data.or.n > MPC_PARSE_STACK_MIN
|
||||||
if (st <= p->data.or.n) {
|
? malloc(sizeof(mpc_result_t) * p->data.or.n)
|
||||||
if (mpc_stack_peekr(stk, &r)) {
|
: results_stk;
|
||||||
mpc_stack_popr(stk, &r);
|
|
||||||
mpc_stack_popr_err(stk, st-1);
|
for (j = 0; j < p->data.or.n; j++) {
|
||||||
MPC_SUCCESS(r.output);
|
if (mpc_parse_input(i, p->data.or.xs[j], &results[j])) {
|
||||||
|
for (k = 0; k < j; k++) {
|
||||||
|
mpc_err_delete(results[k].error);
|
||||||
}
|
}
|
||||||
if (st < p->data.or.n) { MPC_CONTINUE(st+1, p->data.or.xs[st]); }
|
MPC_SUCCESS(results[j].output;
|
||||||
if (st == p->data.or.n) { MPC_FAILURE(mpc_stack_merger_err(stk, p->data.or.n)); }
|
if (p->data.or.n > MPC_PARSE_STACK_MIN) { free(results); });
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MPC_FAILURE(mpc_err_or((mpc_err_t**)results, j);
|
||||||
|
if (p->data.or.n > MPC_PARSE_STACK_MIN) { free(results); });
|
||||||
|
|
||||||
case MPC_TYPE_AND:
|
case MPC_TYPE_AND:
|
||||||
|
|
||||||
if (p->data.and.n == 0) { MPC_SUCCESS(p->data.and.f(0, NULL)); }
|
if (p->data.and.n == 0) { MPC_SUCCESS(NULL); }
|
||||||
|
|
||||||
if (st == 0) { mpc_input_mark(i); MPC_CONTINUE(st+1, p->data.and.xs[st]); }
|
results = p->data.or.n > MPC_PARSE_STACK_MIN
|
||||||
if (st <= p->data.and.n) {
|
? malloc(sizeof(mpc_result_t) * p->data.or.n)
|
||||||
if (!mpc_stack_peekr(stk, &r)) {
|
: results_stk;
|
||||||
|
|
||||||
|
mpc_input_mark(i);
|
||||||
|
for (j = 0; j < p->data.and.n; j++) {
|
||||||
|
if (!mpc_parse_input(i, p->data.and.xs[j], &results[j])) {
|
||||||
mpc_input_rewind(i);
|
mpc_input_rewind(i);
|
||||||
mpc_stack_popr(stk, &r);
|
for (k = 0; k < j; k++) {
|
||||||
mpc_stack_popr_out(stk, st-1, p->data.and.dxs);
|
p->data.and.dxs[k](results[k].output);
|
||||||
MPC_FAILURE(r.error);
|
|
||||||
}
|
}
|
||||||
if (st < p->data.and.n) { MPC_CONTINUE(st+1, p->data.and.xs[st]); }
|
MPC_FAILURE(results[j].error;
|
||||||
if (st == p->data.and.n) { mpc_input_unmark(i); MPC_SUCCESS(mpc_stack_merger_out(stk, p->data.and.n, p->data.and.f)); }
|
if (p->data.or.n > MPC_PARSE_STACK_MIN) { free(results); });
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
mpc_input_unmark(i);
|
||||||
|
|
||||||
|
MPC_SUCCESS(p->data.and.f(j, (mpc_val_t**)results);
|
||||||
|
if (p->data.or.n > MPC_PARSE_STACK_MIN) { free(results); });
|
||||||
|
|
||||||
/* End */
|
/* End */
|
||||||
|
|
||||||
@@ -1197,13 +974,11 @@ int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) {
|
|||||||
|
|
||||||
MPC_FAILURE(mpc_err_fail(i->filename, i->state, "Unknown Parser Type Id!"));
|
MPC_FAILURE(mpc_err_fail(i->filename, i->state, "Unknown Parser Type Id!"));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return mpc_stack_terminate(stk, final);
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef MPC_CONTINUE
|
|
||||||
#undef MPC_SUCCESS
|
#undef MPC_SUCCESS
|
||||||
#undef MPC_FAILURE
|
#undef MPC_FAILURE
|
||||||
#undef MPC_PRIMITIVE
|
#undef MPC_PRIMITIVE
|
||||||
@@ -2011,7 +1786,7 @@ static mpc_val_t *mpcf_re_range(mpc_val_t *x) {
|
|||||||
start = s[i-1]+1;
|
start = s[i-1]+1;
|
||||||
end = s[i+1]-1;
|
end = s[i+1]-1;
|
||||||
for (j = start; j <= end; j++) {
|
for (j = start; j <= end; j++) {
|
||||||
range = realloc(range, strlen(range) + 1 + 1);
|
range = realloc(range, strlen(range) + 1 + 1 + 1);
|
||||||
range[strlen(range) + 1] = '\0';
|
range[strlen(range) + 1] = '\0';
|
||||||
range[strlen(range) + 0] = j;
|
range[strlen(range) + 0] = j;
|
||||||
}
|
}
|
||||||
@@ -2230,7 +2005,7 @@ static mpc_val_t *mpcf_unescape_new(mpc_val_t *x, const char *input, const char
|
|||||||
while (output[i]) {
|
while (output[i]) {
|
||||||
if ((*(s+0)) == output[i][0] &&
|
if ((*(s+0)) == output[i][0] &&
|
||||||
(*(s+1)) == output[i][1]) {
|
(*(s+1)) == output[i][1]) {
|
||||||
y = realloc(y, strlen(y) + 2);
|
y = realloc(y, strlen(y) + 1 + 1);
|
||||||
buff[0] = input[i]; buff[1] = '\0';
|
buff[0] = input[i]; buff[1] = '\0';
|
||||||
strcat(y, buff);
|
strcat(y, buff);
|
||||||
found = 1;
|
found = 1;
|
||||||
@@ -2241,7 +2016,7 @@ static mpc_val_t *mpcf_unescape_new(mpc_val_t *x, const char *input, const char
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
y = realloc(y, strlen(y) + 2);
|
y = realloc(y, strlen(y) + 1 + 1);
|
||||||
buff[0] = *s; buff[1] = '\0';
|
buff[0] = *s; buff[1] = '\0';
|
||||||
strcat(y, buff);
|
strcat(y, buff);
|
||||||
}
|
}
|
||||||
@@ -3363,7 +3138,6 @@ static void mpc_optimise_unretained(mpc_parser_t *p, int force) {
|
|||||||
|
|
||||||
int i, n, m;
|
int i, n, m;
|
||||||
mpc_parser_t *t;
|
mpc_parser_t *t;
|
||||||
mpc_parser_t swp;
|
|
||||||
|
|
||||||
if (p->retained && !force) { return; }
|
if (p->retained && !force) { return; }
|
||||||
|
|
||||||
@@ -3428,10 +3202,11 @@ static void mpc_optimise_unretained(mpc_parser_t *p, int force) {
|
|||||||
&& p->data.and.xs[0]->type == MPC_TYPE_PASS
|
&& p->data.and.xs[0]->type == MPC_TYPE_PASS
|
||||||
&& !p->data.and.xs[0]->retained
|
&& !p->data.and.xs[0]->retained
|
||||||
&& p->data.and.f == mpcf_fold_ast) {
|
&& p->data.and.f == mpcf_fold_ast) {
|
||||||
memcpy(&swp, p->data.and.xs[1], sizeof(mpc_parser_t));
|
t = p->data.and.xs[1];
|
||||||
mpc_delete(p->data.and.xs[0]);
|
mpc_delete(p->data.and.xs[0]);
|
||||||
free(p->data.and.xs); free(p->data.and.dxs);
|
free(p->data.and.xs); free(p->data.and.dxs); free(p->name);
|
||||||
memcpy(p, &swp, sizeof(mpc_parser_t));
|
memcpy(p, t, sizeof(mpc_parser_t));
|
||||||
|
free(t);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3477,10 +3252,11 @@ static void mpc_optimise_unretained(mpc_parser_t *p, int force) {
|
|||||||
&& p->data.and.xs[0]->data.lift.lf == mpcf_ctor_str
|
&& p->data.and.xs[0]->data.lift.lf == mpcf_ctor_str
|
||||||
&& !p->data.and.xs[0]->retained
|
&& !p->data.and.xs[0]->retained
|
||||||
&& p->data.and.f == mpcf_strfold) {
|
&& p->data.and.f == mpcf_strfold) {
|
||||||
memcpy(&swp, p->data.and.xs[1], sizeof(mpc_parser_t));
|
t = p->data.and.xs[1];
|
||||||
mpc_delete(p->data.and.xs[0]);
|
mpc_delete(p->data.and.xs[0]);
|
||||||
free(p->data.and.xs); free(p->data.and.dxs);
|
free(p->data.and.xs); free(p->data.and.dxs); free(p->name);
|
||||||
memcpy(p, &swp, sizeof(mpc_parser_t));
|
memcpy(p, t, sizeof(mpc_parser_t));
|
||||||
|
free(t);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user