###### parser functions
- static int shift(struct parser *p, struct frame *next,
+ static int shift(struct parser *p,
+ short sym, short indents, short start_of_line,
void *asn,
const struct state states[])
{
// Push an entry onto the stack
+ struct frame next = {0};
int newstate = p->tos
? search(&states[p->stack[p->tos-1].state],
- next->sym)
+ sym)
: 0;
if (newstate < 0)
return 0;
p->asn_stack = realloc(p->asn_stack, p->stack_size
* sizeof(p->asn_stack[0]));
}
- next->state = newstate;
+ next.sym = sym;
+ next.indents = indents;
+ next.state = newstate;
if (states[newstate].starts_line)
- next->newline_permitted = 1;
- else if (next->indents)
- next->newline_permitted = 0;
+ next.newline_permitted = 1;
+ else if (indents)
+ next.newline_permitted = 0;
else if (p->tos)
- next->newline_permitted =
+ next.newline_permitted =
p->stack[p->tos-1].newline_permitted;
else
- next->newline_permitted = 0;
+ next.newline_permitted = 0;
- if (next->since_newline) {
+ if (!start_of_line) {
if (p->tos)
- next->since_newline = p->stack[p->tos-1].since_newline + 1;
+ next.since_newline = p->stack[p->tos-1].since_newline + 1;
else
- next->since_newline = 1;
+ next.since_newline = 1;
}
- if (next->indents)
- next->since_indent = 0;
+ if (indents)
+ next.since_indent = 0;
else if (p->tos)
- next->since_indent = p->stack[p->tos-1].since_indent + 1;
+ next.since_indent = p->stack[p->tos-1].since_indent + 1;
else
- next->since_indent = 1;
+ next.since_indent = 1;
- p->stack[p->tos] = *next;
+ p->stack[p->tos] = next;
p->asn_stack[p->tos] = asn;
p->tos++;
return 1;
###### parser functions
- static void pop(struct parser *p, int num, struct frame *next,
- void(*do_free)(short sym, void *asn))
+ static int pop(struct parser *p, int num,
+ short *start_of_line,
+ void(*do_free)(short sym, void *asn))
{
int i;
+ short indents;
p->tos -= num;
- next->since_newline =
- p->stack[p->tos].since_newline;
- next->indents = 0;
+ if (start_of_line)
+ *start_of_line =
+ !p->stack[p->tos].since_newline;
+ indents = 0;
for (i = 0; i < num; i++) {
- next->indents += p->stack[p->tos+i].indents;
+ indents += p->stack[p->tos+i].indents;
do_free(p->stack[p->tos+i].sym,
p->asn_stack[p->tos+i]);
}
+ return indents;
}
### Memory allocation
int accepted = 0;
void *ret = NULL;
- shift(&p, &next, NULL, states);
+ shift(&p, TK_eof, 0, 1, NULL, states);
while (!accepted) {
struct token *err_tk;
struct frame *tos = &p.stack[p.tos-1];
states[tos->state].reduce_size <= tos->since_newline)
goto force_reduce;
}
- if (shift(&p, &next, tk, states)) {
+ if (shift(&p, tk->num, 0, tk->num == TK_newline, tk, states)) {
next.since_newline = !(tk->num == TK_newline);
next.indents = 0;
tk = NULL;
int size = nextstate->reduce_size;
int bufsize;
static char buf[16*1024];
- struct frame frame;
- frame.sym = nextstate->reduce_sym;
+ short indents, start_of_line;
body = p.asn_stack + (p.tos - size);
bufsize = do_reduce(prod, body, config, buf);
if (size)
- pop(&p, size, &frame, do_free);
+ indents = pop(&p, size, &start_of_line,
+ do_free);
else {
- frame.indents = next.indents;
- frame.since_newline = 1;
+ indents = next.indents;
+ start_of_line = 0;
next.indents = 0;
}
res = memdup(buf, bufsize);
memset(buf, 0, bufsize);
- if (!shift(&p, &frame, res, states)) {
+ if (!shift(&p, nextstate->reduce_sym,
+ indents, start_of_line,
+ res, states)) {
if (prod != 0) abort();
accepted = 1;
ret = res;
if (tk->num == TK_out) {
// Indent problem - synthesise tokens to get us
// out of here.
- struct frame frame = { 0 };
fprintf(stderr, "Synthesize %d to handle indent problem\n", states[tos->state].shift_sym);
- frame.sym = states[tos->state].shift_sym;
- frame.since_newline = 1;
- shift(&p, &frame, tok_copy(*tk), states);
+ shift(&p, states[tos->state].shift_sym,
+ 0, 1, tok_copy(*tk), states);
// FIXME need to report this error somehow
parser_trace_action(trace, "Synthesize");
continue;
* we find one that is acceptable.
*/
parser_trace_action(trace, "ERROR");
+ short indents = 0, start_of_line;
err_tk = tok_copy(*tk);
next.sym = TK_error;
- while (shift(&p, &next, err_tk, states) == 0
+ while (shift(&p, TK_error, next.indents, !next.since_newline,
+ err_tk, states) == 0
&& p.tos > 0)
// discard this state
- pop(&p, 1, &next, do_free);
+ indents += pop(&p, 1, &start_of_line, do_free);
if (p.tos == 0) {
free(err_tk);
// no state accepted TK_error
free(tk);
tk = tok_copy(token_next(tokens));
if (tk->num == TK_in)
- next.indents += 1;
+ indents += 1;
if (tk->num == TK_out) {
- if (next.indents == 0)
+ if (indents == 0)
break;
- next.indents -= 1;
+ indents -= 1;
// FIXME update since_indent here
}
}
if (p.tos == 0 && tk->num == TK_eof)
break;
+ tos = &p.stack[p.tos-1];
+ tos->indents += indents;
}
free(tk);
if (p.tos)
- pop(&p, p.tos, &next, do_free);
+ pop(&p, p.tos, NULL, do_free);
free(p.asn_stack);
free(p.stack);
return ret;