]> ocean-lang.org Git - ocean/commitdiff
parsergen: don't use 'frame' to pass args to shift() or receive from pop()
authorNeilBrown <neil@brown.name>
Fri, 3 Oct 2014 03:24:36 +0000 (13:24 +1000)
committerNeilBrown <neil@brown.name>
Fri, 3 Oct 2014 03:24:36 +0000 (13:24 +1000)
'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 <neil@brown.name>
csrc/parsergen.mdc

index f87d83f7acab966c57d2291191482edf7b25a1f5..646a8e7d13bc787e5e383c053980fe358d3e4ede 100644 (file)
@@ -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;