From: NeilBrown Date: Fri, 3 Oct 2014 03:24:36 +0000 (+1000) Subject: parsergen: don't use 'frame' to pass args to shift() or receive from pop() X-Git-Tag: workingparser~13 X-Git-Url: https://ocean-lang.org/code/?p=ocean;a=commitdiff_plain;h=4eb97e40e3bda161765b78716a52516be329de7c parsergen: don't use 'frame' to pass args to shift() or receive from pop() 'struct frame' holds a number of fields that shift() ignores and pop() doesn't fill in. So it is a bit confusing to see a frame passed in and mostly ignored. So just pass in the fields that are actually needed. This fixes a bug where 'since_newline' was set wrongly when a newline is shifted. Signed-off-by: NeilBrown --- diff --git a/csrc/parsergen.mdc b/csrc/parsergen.mdc index f87d83f..646a8e7 100644 --- a/csrc/parsergen.mdc +++ b/csrc/parsergen.mdc @@ -2503,14 +2503,16 @@ So we walk down: ###### 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; @@ -2521,31 +2523,33 @@ So we walk down: 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; @@ -2561,19 +2565,23 @@ removed. It is called _after_ we reduce a production, just before we ###### 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 @@ -2649,7 +2657,7 @@ since the last state which could have been at the start of a line. 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]; @@ -2716,7 +2724,7 @@ since the last state which could have been at the start of a line. 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; @@ -2732,23 +2740,25 @@ since the last state which could have been at the start of a line. 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; @@ -2759,11 +2769,9 @@ since the last state which could have been at the start of a line. 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; @@ -2776,13 +2784,15 @@ since the last state which could have been at the start of a line. * 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 @@ -2794,20 +2804,22 @@ since the last state which could have been at the start of a line. 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;