From: NeilBrown Date: Sun, 24 Nov 2013 06:36:41 +0000 (+1100) Subject: parsegen: unify the "next" frame to go onto stack. X-Git-Tag: indentparser~3 X-Git-Url: https://ocean-lang.org/code/?p=ocean;a=commitdiff_plain;h=35e535a5a5fc32421f3a5205fbe290ab2bb9fade parsegen: unify the "next" frame to go onto stack. We current have a current 'state' in the parser and a 'sym' which is a local variable passed around in different ways. Both of these get pushed onto the stack at the next 'shift'. We will shortly add some more fields to the stack frame, so unify 'state' and 'sym' in to a 'next' struct in the parser struct which can easily be extended. Signed-off-by: NeilBrown --- diff --git a/csrc/parsergen.mdc b/csrc/parsergen.mdc index 7b6664d..ec9b8f2 100644 --- a/csrc/parsergen.mdc +++ b/csrc/parsergen.mdc @@ -2251,14 +2251,17 @@ The `state` is the most important one and guides the parsing process. The freeing function. The symbol leads us to the right free function through `do_free`. +As well as the stack of frames we have a `next` frame which is +assembled from the incoming token and other information prior to +pushing it onto the stack. + ###### parser functions struct parser { - int state; struct frame { short state; short sym; - } *stack; + } *stack, next; void **asn_stack; int stack_size; int tos; @@ -2285,11 +2288,11 @@ if needed and pushed all the information onto the stacks. ###### parser functions static int shift(struct parser *p, - int sym, void *asn, + void *asn, const struct state states[]) { // Push an entry onto the stack - int newstate = search(&states[p->state], sym); + int newstate = search(&states[p->next.state], p->next.sym); if (newstate < 0) return 0; if (p->tos >= p->stack_size) { @@ -2299,11 +2302,10 @@ if needed and pushed all the information onto the stacks. p->asn_stack = realloc(p->asn_stack, p->stack_size * sizeof(p->asn_stack[0])); } - p->stack[p->tos].state = p->state; - p->stack[p->tos].sym = sym; + p->stack[p->tos] = p->next; p->asn_stack[p->tos] = asn; p->tos++; - p->state = newstate; + p->next.state = newstate; return 1; } @@ -2322,7 +2324,8 @@ reduce a production, just before we `shift` the nonterminal in. do_free(p->stack[p->tos+i].sym, p->asn_stack[p->tos+i]); - p->state = p->stack[p->tos].state; + if (num) + p->next.state = p->stack[p->tos].state; } ### Memory allocation @@ -2383,28 +2386,29 @@ drop input tokens until we find one we can shift into the new error state. tk = tok_copy(token_next(tokens)); while (!accepted) { + p.next.sym = tk->num; if (trace) parser_trace(trace, &p, tk, states, non_term, knowns); - if (shift(&p, tk->num, tk, states)) { + if (shift(&p, tk, states)) { tk = tok_copy(token_next(tokens)); continue; } - if (states[p.state].reduce_prod >= 0) { + if (states[p.next.state].reduce_prod >= 0) { void **body; - int prod = states[p.state].reduce_prod; - int size = states[p.state].reduce_size; - int sym = states[p.state].reduce_sym; + int prod = states[p.next.state].reduce_prod; + int size = states[p.next.state].reduce_size; int bufsize; static char buf[16*1024]; + p.next.sym = states[p.next.state].reduce_sym; body = p.asn_stack + - (p.tos - states[p.state].reduce_size); + (p.tos - states[p.next.state].reduce_size); bufsize = do_reduce(prod, body, buf); pop(&p, size, do_free); - shift(&p, sym, memdup(buf, bufsize), states); + shift(&p, memdup(buf, bufsize), states); if (prod == 0) accepted = 1; continue; @@ -2416,12 +2420,13 @@ drop input tokens until we find one we can shift into the new error state. * Then we discard input tokens until * we find one that is acceptable. */ - while (shift(&p, TK_error, tk, states) == 0 + p.next.sym = TK_error; + while (shift(&p, tk, states) == 0 && p.tos > 0) // discard this state pop(&p, 1, do_free); tk = tok_copy(*tk); - while (search(&states[p.state], tk->num) < 0 && + while (search(&states[p.next.state], tk->num) < 0 && tk->num != TK_eof) { free(tk); tk = tok_copy(token_next(tokens)); @@ -2491,7 +2496,7 @@ end inside square brackets. trace); fputs(" ", trace); } - fprintf(trace, "(%d) [", p->state); + fprintf(trace, "(%d) [", p->next.state); if (tk->num < TK_reserved && reserved_words[tk->num] != NULL) fputs(reserved_words[tk->num], trace);