Switched parsing to use C function stack

This commit is contained in:
Daniel Holden
2015-11-10 20:25:39 +00:00
parent 991a6e4156
commit 31889d86c3

646
mpc.c
View File

@@ -748,225 +748,6 @@ struct mpc_parser_t {
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
** is written in about 200 lines of C.
@@ -977,233 +758,227 @@ static mpc_err_t *mpc_stack_merger_err(mpc_stack_t *s, int n) {
** Particularly nice are the `or` and `and`
** types which have a broken but mirrored structure
** 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) mpc_stack_popp(stk, &p, &st); mpc_stack_pushr(stk, mpc_result_out(x), 1); continue
#define MPC_FAILURE(x) mpc_stack_popp(stk, &p, &st); mpc_stack_pushr(stk, mpc_result_err(x), 0); continue
#define MPC_PRIMITIVE(x, f) if (f) { MPC_SUCCESS(x); } else { MPC_FAILURE(mpc_err_fail(i->filename, i->state, "Incorrect Input")); }
#define MPC_SUCCESS(x) r->output = x; return 1
#define MPC_FAILURE(x) r->error = x; return 0
#define MPC_PRIMITIVE(x) \
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) {
/* Stack */
int st = 0;
mpc_parser_t *p = NULL;
mpc_stack_t *stk = mpc_stack_new(i->filename);
/* Variables */
char *s;
mpc_result_t r;
enum {
MPC_PARSE_STACK_MIN = 8
};
/* Go! */
mpc_stack_pushp(stk, init);
int mpc_parse_input(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r) {
while (!mpc_stack_empty(stk)) {
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;
switch (p->type) {
/* Basic Parsers */
case MPC_TYPE_ANY: MPC_PRIMITIVE(mpc_input_any(i, (char**)&r->output));
case MPC_TYPE_SINGLE: MPC_PRIMITIVE(mpc_input_char(i, p->data.single.x, (char**)&r->output));
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(mpc_input_oneof(i, p->data.string.x, (char**)&r->output));
case MPC_TYPE_NONEOF: MPC_PRIMITIVE(mpc_input_noneof(i, p->data.string.x, (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));
/* Other parsers */
mpc_stack_peepp(stk, &p, &st);
case MPC_TYPE_UNDEFINED: MPC_FAILURE(mpc_err_fail(i->filename, i->state, "Parser Undefined!"));
case MPC_TYPE_PASS: MPC_SUCCESS(NULL);
case MPC_TYPE_FAIL: MPC_FAILURE(mpc_err_fail(i->filename, i->state, p->data.fail.m));
case MPC_TYPE_LIFT: MPC_SUCCESS(p->data.lift.lf());
case MPC_TYPE_LIFT_VAL: MPC_SUCCESS(p->data.lift.x);
case MPC_TYPE_STATE: MPC_SUCCESS(mpc_state_copy(i->state));
switch (p->type) {
case MPC_TYPE_ANCHOR:
if (mpc_input_anchor(i, p->data.anchor.f)) {
MPC_SUCCESS(NULL);
} else {
MPC_FAILURE(mpc_err_new(i->filename, i->state, "anchor", mpc_input_peekc(i)));
}
/* Application Parsers */
case MPC_TYPE_EXPECT:
if (mpc_parse_input(i, p->data.expect.x, r)) {
MPC_SUCCESS(r->output);
} else {
mpc_err_delete(r->error);
MPC_FAILURE(mpc_err_new(i->filename, i->state, p->data.expect.m, mpc_input_peekc(i)));
}
case MPC_TYPE_APPLY:
if (mpc_parse_input(i, p->data.apply.x, r)) {
MPC_SUCCESS(p->data.apply.f(r->output));
} else {
MPC_FAILURE(r->output);
}
case MPC_TYPE_APPLY_TO:
if (mpc_parse_input(i, p->data.apply_to.x, r)) {
MPC_SUCCESS(p->data.apply_to.f(r->output, p->data.apply_to.d));
} else {
MPC_FAILURE(r->error);
}
case MPC_TYPE_PREDICT:
mpc_input_backtrack_disable(i);
if (mpc_parse_input(i, p->data.predict.x, r)) {
mpc_input_backtrack_enable(i);
MPC_SUCCESS(r->output);
} else {
mpc_input_backtrack_enable(i);
MPC_FAILURE(r->error);
}
/* Optional Parsers */
/* TODO: Update Not Error Message */
case MPC_TYPE_NOT:
mpc_input_mark(i);
if (mpc_parse_input(i, p->data.not.x, r)) {
mpc_input_rewind(i);
p->data.not.dx(r->output);
MPC_FAILURE(mpc_err_new(i->filename, i->state, "opposite", mpc_input_peekc(i)));
} else {
mpc_input_unmark(i);
mpc_err_delete(r->error);
MPC_SUCCESS(p->data.not.lf());
}
case MPC_TYPE_MAYBE:
if (mpc_parse_input(i, p->data.not.x, r)) {
MPC_SUCCESS(r->output);
} else {
mpc_err_delete(r->error);
MPC_SUCCESS(p->data.not.lf());
}
/* Repeat Parsers */
case MPC_TYPE_MANY:
/* Basic Parsers */
results = malloc(sizeof(mpc_result_t) * results_slots);
while (mpc_parse_input(i, p->data.repeat.x, &results[j])) {
j++;
if (j >= results_slots) {
results_slots = j + j / 2;
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:
results = malloc(sizeof(mpc_result_t) * results_slots);
while (mpc_parse_input(i, p->data.repeat.x, &results[j])) {
j++;
if (j >= results_slots) {
results_slots = j + j / 2;
results = realloc(results, sizeof(mpc_result_t) * results_slots);
}
}
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:
results = p->data.repeat.n > MPC_PARSE_STACK_MIN
? malloc(sizeof(mpc_result_t) * p->data.repeat.n)
: results_stk;
while (mpc_parse_input(i, p->data.repeat.x, &results[j])) {
j++;
if (j == p->data.repeat.n) { break; }
}
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 */
case MPC_TYPE_OR:
if (p->data.or.n == 0) { MPC_SUCCESS(NULL); }
results = p->data.or.n > MPC_PARSE_STACK_MIN
? malloc(sizeof(mpc_result_t) * p->data.or.n)
: results_stk;
for (j = 0; j < p->data.or.n; j++) {
if (mpc_parse_input(i, p->data.or.xs[j], &results[j])) {
for (k = 0; k < j; k++) {
mpc_err_delete(results[k].error);
}
MPC_SUCCESS(results[j].output;
if (p->data.or.n > MPC_PARSE_STACK_MIN) { free(results); });
}
}
case MPC_TYPE_ANY: MPC_PRIMITIVE(s, mpc_input_any(i, &s));
case MPC_TYPE_SINGLE: MPC_PRIMITIVE(s, mpc_input_char(i, p->data.single.x, &s));
case MPC_TYPE_RANGE: MPC_PRIMITIVE(s, mpc_input_range(i, p->data.range.x, p->data.range.y, &s));
case MPC_TYPE_ONEOF: MPC_PRIMITIVE(s, mpc_input_oneof(i, p->data.string.x, &s));
case MPC_TYPE_NONEOF: MPC_PRIMITIVE(s, mpc_input_noneof(i, p->data.string.x, &s));
case MPC_TYPE_SATISFY: MPC_PRIMITIVE(s, mpc_input_satisfy(i, p->data.satisfy.f, &s));
case MPC_TYPE_STRING: MPC_PRIMITIVE(s, mpc_input_string(i, p->data.string.x, &s));
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:
/* Other parsers */
if (p->data.and.n == 0) { MPC_SUCCESS(NULL); }
case MPC_TYPE_UNDEFINED: MPC_FAILURE(mpc_err_fail(i->filename, i->state, "Parser Undefined!"));
case MPC_TYPE_PASS: MPC_SUCCESS(NULL);
case MPC_TYPE_FAIL: MPC_FAILURE(mpc_err_fail(i->filename, i->state, p->data.fail.m));
case MPC_TYPE_LIFT: MPC_SUCCESS(p->data.lift.lf());
case MPC_TYPE_LIFT_VAL: MPC_SUCCESS(p->data.lift.x);
case MPC_TYPE_STATE: MPC_SUCCESS(mpc_state_copy(i->state));
results = p->data.or.n > MPC_PARSE_STACK_MIN
? malloc(sizeof(mpc_result_t) * p->data.or.n)
: results_stk;
case MPC_TYPE_ANCHOR:
if (mpc_input_anchor(i, p->data.anchor.f)) {
MPC_SUCCESS(NULL);
} else {
MPC_FAILURE(mpc_err_new(i->filename, i->state, "anchor", mpc_input_peekc(i)));
}
/* Application Parsers */
case MPC_TYPE_EXPECT:
if (st == 0) { MPC_CONTINUE(1, p->data.expect.x); }
if (st == 1) {
if (mpc_stack_popr(stk, &r)) {
MPC_SUCCESS(r.output);
} else {
mpc_err_delete(r.error);
MPC_FAILURE(mpc_err_new(i->filename, i->state, p->data.expect.m, mpc_input_peekc(i)));
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);
for (k = 0; k < j; k++) {
p->data.and.dxs[k](results[k].output);
}
MPC_FAILURE(results[j].error;
if (p->data.or.n > MPC_PARSE_STACK_MIN) { free(results); });
}
}
mpc_input_unmark(i);
case MPC_TYPE_APPLY:
if (st == 0) { MPC_CONTINUE(1, p->data.apply.x); }
if (st == 1) {
if (mpc_stack_popr(stk, &r)) {
MPC_SUCCESS(p->data.apply.f(r.output));
} else {
MPC_FAILURE(r.error);
}
}
MPC_SUCCESS(p->data.and.f(j, (mpc_val_t**)results);
if (p->data.or.n > MPC_PARSE_STACK_MIN) { free(results); });
/* End */
default:
case MPC_TYPE_APPLY_TO:
if (st == 0) { MPC_CONTINUE(1, p->data.apply_to.x); }
if (st == 1) {
if (mpc_stack_popr(stk, &r)) {
MPC_SUCCESS(p->data.apply_to.f(r.output, p->data.apply_to.d));
} else {
MPC_FAILURE(r.error);
}
}
case MPC_TYPE_PREDICT:
if (st == 0) { mpc_input_backtrack_disable(i); MPC_CONTINUE(1, p->data.predict.x); }
if (st == 1) {
mpc_input_backtrack_enable(i);
mpc_stack_popp(stk, &p, &st);
continue;
}
/* Optional Parsers */
/* TODO: Update Not Error Message */
case MPC_TYPE_NOT:
if (st == 0) { mpc_input_mark(i); MPC_CONTINUE(1, p->data.not.x); }
if (st == 1) {
if (mpc_stack_popr(stk, &r)) {
mpc_input_rewind(i);
p->data.not.dx(r.output);
MPC_FAILURE(mpc_err_new(i->filename, i->state, "opposite", mpc_input_peekc(i)));
} else {
mpc_input_unmark(i);
mpc_stack_err(stk, r.error);
MPC_SUCCESS(p->data.not.lf());
}
}
case MPC_TYPE_MAYBE:
if (st == 0) { MPC_CONTINUE(1, p->data.not.x); }
if (st == 1) {
if (mpc_stack_popr(stk, &r)) {
MPC_SUCCESS(r.output);
} else {
mpc_stack_err(stk, r.error);
MPC_SUCCESS(p->data.not.lf());
}
}
/* Repeat Parsers */
case MPC_TYPE_MANY:
if (st == 0) { MPC_CONTINUE(st+1, p->data.repeat.x); }
if (st > 0) {
if (mpc_stack_peekr(stk, &r)) {
MPC_CONTINUE(st+1, p->data.repeat.x);
} 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));
}
}
case MPC_TYPE_MANY1:
if (st == 0) { MPC_CONTINUE(st+1, p->data.repeat.x); }
if (st > 0) {
if (mpc_stack_peekr(stk, &r)) {
MPC_CONTINUE(st+1, p->data.repeat.x);
} else {
if (st == 1) {
mpc_stack_popr(stk, &r);
MPC_FAILURE(mpc_err_many1(r.error));
} 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));
}
}
}
case MPC_TYPE_COUNT:
if (st == 0) { mpc_input_mark(i); MPC_CONTINUE(st+1, p->data.repeat.x); }
if (st > 0) {
if (!mpc_stack_peekr(stk, &r)) {
mpc_stack_popr(stk, &r);
mpc_stack_popr_out_single(stk, st-1, p->data.repeat.dx);
mpc_input_rewind(i);
MPC_FAILURE(mpc_err_count(r.error, p->data.repeat.n));
} else {
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));
}
}
}
/* Combinatory Parsers */
case MPC_TYPE_OR:
if (p->data.or.n == 0) { MPC_SUCCESS(NULL); }
if (st == 0) { MPC_CONTINUE(st+1, p->data.or.xs[st]); }
if (st <= p->data.or.n) {
if (mpc_stack_peekr(stk, &r)) {
mpc_stack_popr(stk, &r);
mpc_stack_popr_err(stk, st-1);
MPC_SUCCESS(r.output);
}
if (st < p->data.or.n) { MPC_CONTINUE(st+1, p->data.or.xs[st]); }
if (st == p->data.or.n) { MPC_FAILURE(mpc_stack_merger_err(stk, p->data.or.n)); }
}
case MPC_TYPE_AND:
if (p->data.and.n == 0) { MPC_SUCCESS(p->data.and.f(0, NULL)); }
if (st == 0) { mpc_input_mark(i); MPC_CONTINUE(st+1, p->data.and.xs[st]); }
if (st <= p->data.and.n) {
if (!mpc_stack_peekr(stk, &r)) {
mpc_input_rewind(i);
mpc_stack_popr(stk, &r);
mpc_stack_popr_out(stk, st-1, p->data.and.dxs);
MPC_FAILURE(r.error);
}
if (st < p->data.and.n) { MPC_CONTINUE(st+1, p->data.and.xs[st]); }
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)); }
}
/* End */
default:
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_FAILURE
#undef MPC_PRIMITIVE
@@ -2011,7 +1786,7 @@ static mpc_val_t *mpcf_re_range(mpc_val_t *x) {
start = s[i-1]+1;
end = s[i+1]-1;
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) + 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]) {
if ((*(s+0)) == output[i][0] &&
(*(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';
strcat(y, buff);
found = 1;
@@ -2241,7 +2016,7 @@ static mpc_val_t *mpcf_unescape_new(mpc_val_t *x, const char *input, const char
}
if (!found) {
y = realloc(y, strlen(y) + 2);
y = realloc(y, strlen(y) + 1 + 1);
buff[0] = *s; buff[1] = '\0';
strcat(y, buff);
}
@@ -3363,7 +3138,6 @@ static void mpc_optimise_unretained(mpc_parser_t *p, int force) {
int i, n, m;
mpc_parser_t *t;
mpc_parser_t swp;
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]->retained
&& 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]);
free(p->data.and.xs); free(p->data.and.dxs);
memcpy(p, &swp, sizeof(mpc_parser_t));
free(p->data.and.xs); free(p->data.and.dxs); free(p->name);
memcpy(p, t, sizeof(mpc_parser_t));
free(t);
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]->retained
&& 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]);
free(p->data.and.xs); free(p->data.and.dxs);
memcpy(p, &swp, sizeof(mpc_parser_t));
free(p->data.and.xs); free(p->data.and.dxs); free(p->name);
memcpy(p, t, sizeof(mpc_parser_t));
free(t);
continue;
}