]> ocean-lang.org Git - ocean/blobdiff - csrc/parsergen.mdc
parsergen: split out reduce step of parser
[ocean] / csrc / parsergen.mdc
index 0986fc28c2b2d0d411eac8ed71d822fb0e323c01..6eb43181006fca10c080b545a6f47b85173636ac 100644 (file)
@@ -2768,6 +2768,45 @@ in the thing that preceed:
 Here the NEWLINE will be shifted because nothing can be reduced until
 the `if` is seen.
 
+We have already discussed the bulk of the handling of a "reduce" action,
+with the `pop()` and `shift()` functions doing much of the work.  There
+is a little more complexity needed to manage storage for the asn (Abstract
+Syntax Node), and also a test of whether the reduction is permitted.
+
+When we try to shift the result of reducing production-zero, it will
+fail because there is no next state.  In this case the asn will not have
+been stored on the stack, so it get stored in the `ret` variable, and we
+report that that input has been accepted.
+
+###### parser vars
+
+       void *ret = NULL;
+
+###### try reduce
+
+       if (states[tos->state].reduce_prod >= 0) {
+               void **body;
+               void *res;
+               const struct state *nextstate = &states[tos->state];
+               int prod = nextstate->reduce_prod;
+               int size = nextstate->reduce_size;
+               int res_size = nextstate->result_size;
+
+               body = p.asn_stack + (p.tos - size);
+               res = res_size ? calloc(1, res_size) : NULL;
+               res_size = do_reduce(prod, body, config, res);
+               if (res_size != nextstate->result_size)
+                       abort();
+               pop(&p, size, do_free);
+               if (!shift(&p, nextstate->reduce_sym, res, states)) {
+                       accepted = 1;
+                       ret = res;
+                       parser_trace_action(trace, "Accept");
+               } else
+                       parser_trace_action(trace, "Reduce");
+               continue;
+       }
+
 If we can neither shift nor reduce we have an error to handle.  There
 are two possible responses to an error: we can pop single frames off the
 stack until we find a frame that can shift `TK_error`, or we can discard
@@ -2826,7 +2865,6 @@ dropping tokens until either we manage to shift one, or reach end-of-file.
                struct parser p = { 0 };
                struct token *tk = NULL;
                int accepted = 0;
-               void *ret = NULL;
                ## parser vars
 
                shift(&p, TK_eof, NULL, states);
@@ -2870,31 +2908,7 @@ dropping tokens until either we manage to shift one, or reach end-of-file.
                                continue;
                        }
 
-                       if (states[tos->state].reduce_prod >= 0) {
-                               void **body;
-                               void *res;
-                               const struct state *nextstate = &states[tos->state];
-                               int prod = nextstate->reduce_prod;
-                               int size = nextstate->reduce_size;
-                               int res_size = nextstate->result_size;
-
-                               body = p.asn_stack + (p.tos - size);
-                               res = res_size ? calloc(1, res_size) : NULL;
-                               res_size = do_reduce(prod, body, config, res);
-                               if (res_size != nextstate->result_size)
-                                       abort();
-
-                               pop(&p, size, do_free);
-
-                               if (!shift(&p, nextstate->reduce_sym,
-                                          res, states)) {
-                                       if (prod != 0) abort();
-                                       accepted = 1;
-                                       ret = res;
-                               }
-                               parser_trace_action(trace, "Reduce");
-                               continue;
-                       }
+                       ## try reduce
                        ## handle error
                }
                free(tk);