]> ocean-lang.org Git - ocean/blobdiff - csrc/parsergen.mdc
parsergen: fix a couple of typos in text.
[ocean] / csrc / parsergen.mdc
index 2cd4f5c84534903f114d696939cb698d125e1cd3..1bb813e78318d20e6285db273abdae2d0086c7b4 100644 (file)
@@ -891,7 +891,7 @@ compute it in a repetitive manner similar to `set_nullable`.
 ### Building the `first` sets
 
 When calculating what can follow a particular non-terminal, we will need to
-know what the "first" terminal in an subsequent non-terminal might be.  So
+know what the "first" terminal in any subsequent non-terminal might be.  So
 we calculate the `first` set for every non-terminal and store them in an
 array.  We don't bother recording the "first" set for terminals as they are
 trivial.
@@ -2347,6 +2347,7 @@ pushing it onto the stack.
                        short sym;
                        short starts_indented;
                        short indents;
+                       short newline_permitted;
                } *stack, next;
                void **asn_stack;
                int stack_size;
@@ -2369,7 +2370,7 @@ that we shift when we can, and reduce when we cannot.  So the `shift`
 function reports if it could.
 
 So `shift` finds the next state.  If that succeed it extends the allocations
-if needed and pushed all the information onto the stacks.
+if needed and pushes all the information onto the stacks.
 
 ###### parser functions
 
@@ -2394,6 +2395,9 @@ if needed and pushed all the information onto the stacks.
                p->next.state = newstate;
                p->next.indents = 0;
                p->next.starts_indented = 0;
+               // if new state doesn't start a line, we inherit newline_permitted status
+               if (states[newstate].starts_line)
+                       p->next.newline_permitted = 1;
                return 1;
        }
 
@@ -2417,6 +2421,9 @@ reduce a production, just before we `shift` the nonterminal in.
                if (num) {
                        p->next.state = p->stack[p->tos].state;
                        p->next.starts_indented = p->stack[p->tos].starts_indented;
+                       p->next.newline_permitted = p->stack[p->tos].newline_permitted;
+                       if (p->next.indents > p->next.starts_indented)
+                               p->next.newline_permitted = 0;
                }
        }
 
@@ -2507,6 +2514,13 @@ at the start of a production.
                                    (p.stack[p.tos-1].indents == 1 &&
                                     states[p.next.state].reduce_size > 1)) {
                                        p.stack[p.tos-1].indents -= 1;
+                                       if (p.stack[p.tos-1].indents == p.stack[p.tos-1].starts_indented) {
+                                               // no internal indent any more, reassess 'newline_permitted'
+                                               if (states[p.stack[p.tos-1].state].starts_line)
+                                                       p.stack[p.tos-1].newline_permitted = 1;
+                                               else if (p.tos > 1)
+                                                       p.stack[p.tos-1].newline_permitted = p.stack[p.tos-2].newline_permitted;
+                                       }
                                        free(tk);
                                        tk = NULL;
                                        continue;
@@ -2514,6 +2528,13 @@ at the start of a production.
                                // fall through and force a REDUCE (as 'shift'
                                // will fail).
                        }
+                       if (p.next.sym == TK_newline) {
+                               if (! p.stack[p.tos-1].newline_permitted) {
+                                       free(tk);
+                                       tk = NULL;
+                                       continue;
+                               }
+                       }
                        if (shift(&p, tk, states)) {
                                tk = NULL;
                                continue;
@@ -2623,6 +2644,19 @@ end inside square brackets.
                [TK_newline]      = "NEWLINE",
                [TK_eof]          = "$eof",
        };
+       static void parser_trace_state(FILE *trace, struct frame *f, const struct state states[])
+       {
+               fprintf(trace, "(%d", f->state);
+               if (f->indents)
+                       fprintf(trace, "%c%d", f->starts_indented?':':'.',
+                               f->indents);
+               if (states[f->state].starts_line)
+                       fprintf(trace, "s");
+               if (f->newline_permitted)
+                       fprintf(trace, "n");
+               fprintf(trace, ") ");
+       }
+
        void parser_trace(FILE *trace, struct parser *p,
                          struct token *tk, const struct state states[],
                          const char *non_term[], int knowns)
@@ -2630,7 +2664,7 @@ end inside square brackets.
                int i;
                for (i = 0; i < p->tos; i++) {
                        int sym = p->stack[i].sym;
-                       fprintf(trace, "(%d) ", p->stack[i].state);
+                       parser_trace_state(trace, &p->stack[i], states);
                        if (sym < TK_reserved &&
                            reserved_words[sym] != NULL)
                                fputs(reserved_words[sym], trace);
@@ -2642,7 +2676,8 @@ end inside square brackets.
                                      trace);
                        fputs(" ", trace);
                }
-               fprintf(trace, "(%d) [", p->next.state);
+               parser_trace_state(trace, &p->next, states);
+               fprintf(trace, " [");
                if (tk->num < TK_reserved &&
                    reserved_words[tk->num] != NULL)
                        fputs(reserved_words[tk->num], trace);