]> ocean-lang.org Git - ocean/blobdiff - csrc/parsergen.mdc
parsergen: include virtual symbols in table of non-terminals
[ocean] / csrc / parsergen.mdc
index a7330351d767b52f52ba7b14a802e1b2556dd842..d2ff89844d2e616e0f10e470c0a7dbffde9492a7 100644 (file)
@@ -1776,10 +1776,10 @@ As a special case, if we find a SHIFT/REDUCE conflict, where a
 terminal that could be shifted is in the lookahead set of some
 reducable item, then set check if the reducable item also have
 `TK_newline` in its lookahead set.  If it does, then a newline will
-force and reduction, but anything else can reasonably be shifts, so
+force the reduction, but anything else can reasonably be shifted, so
 that isn't really a conflict.  Such apparent conflicts do not get
-reported.  This will not affect a "tradtional" grammar that does not
-include newlines as token.
+counted, and are reported as non-critical.  This will not affect a
+"traditional" grammar that does not include newlines as token.
 
        static int conflicts_slr(struct grammar *g, enum grammar_type type)
        {
@@ -1826,13 +1826,16 @@ include newlines as token.
                                int k;
                                for (k = 0; k < la.cnt; k++) {
                                        int pos = symset_find(&shifts, la.syms[k]);
-                                       if (pos >= 0 && symset_find(&la, TK_newline) < 0) {
-                                               printf("  State %d has SHIFT/REDUCE conflict on ", i);
+                                       if (pos >= 0) {
+                                               if (symset_find(&la, TK_newline) < 0) {
+                                                       printf("  State %d has SHIFT/REDUCE conflict on ", i);
+                                                       cnt++;
+                                               } else
+                                                       printf("  State %d has non-critical SHIFT/REDUCE conflict on ", i);
                                                prtxt(g->symtab[la.syms[k]]->name);
                                                printf(":\n");
                                                report_item(g, shifts.data[pos]);
                                                report_item(g, itm);
-                                               cnt++;
                                        }
                                        pos = symset_find(&reduce, la.syms[k]);
                                        if (pos < 0) {
@@ -1869,13 +1872,14 @@ pieces of code provided in the grammar file, so they are generated first.
 
 ###### parser_generate
 
-       static void gen_parser(FILE *f, struct grammar *g, char *file, char *name)
+       static void gen_parser(FILE *f, struct grammar *g, char *file, char *name,
+                              struct code_node *pre_reduce)
        {
                gen_known(f, g);
                gen_non_term(f, g);
                gen_goto(f, g);
                gen_states(f, g);
-               gen_reduce(f, g, file);
+               gen_reduce(f, g, file, pre_reduce);
                gen_free(f, g);
 
                fprintf(f, "#line 0 \"gen_parser\"\n");
@@ -1896,7 +1900,9 @@ pieces of code provided in the grammar file, so they are generated first.
 ### Known words table
 
 The known words table is simply an array of terminal symbols.
-The table of nonterminals used for tracing is a similar array.
+The table of nonterminals used for tracing is a similar array.  We
+include virtual symbols in the table of non_terminals to keep the
+numbers right.
 
 ###### functions
 
@@ -1921,7 +1927,7 @@ The table of nonterminals used for tracing is a similar array.
                for (i = TK_reserved;
                     i < g->num_syms;
                     i++)
-                       if (g->symtab[i]->type == Nonterminal)
+                       if (g->symtab[i]->type != Terminal)
                                fprintf(f, "\t\"%.*s\",\n", g->symtab[i]->name.len,
                                        g->symtab[i]->name.txt);
                fprintf(f, "};\n\n");
@@ -2109,14 +2115,18 @@ automatically freed.  This is equivalent to assigning `NULL` to the pointer.
 
 ###### functions
 
-       static void gen_reduce(FILE *f, struct grammar *g, char *file)
+       static void gen_reduce(FILE *f, struct grammar *g, char *file,
+                              struct code_node *code)
        {
                int i;
-               fprintf(f, "#line 0 \"gen_reduce\"\n");
+               fprintf(f, "#line 1 \"gen_reduce\"\n");
                fprintf(f, "static int do_reduce(int prod, void **body, struct token_config *config, void *ret)\n");
                fprintf(f, "{\n");
                fprintf(f, "\tint ret_size = 0;\n");
+               if (code)
+                       code_node_print(f, code, file);
 
+               fprintf(f, "#line 4 \"gen_reduce\"\n");
                fprintf(f, "\tswitch(prod) {\n");
                for (i = 0; i < g->production_count; i++) {
                        struct production *p = g->productions[i];
@@ -2313,6 +2323,7 @@ parser with neither. "grammar" must be provided.
        struct code_node *hdr = NULL;
        struct code_node *code = NULL;
        struct code_node *gram = NULL;
+       struct code_node *pre_reduce = NULL;
        for (s = table; s; s = s->next) {
                struct text sec = s->section;
                if (tag && !strip_tag(&sec, tag))
@@ -2323,6 +2334,8 @@ parser with neither. "grammar" must be provided.
                        code = s->code;
                else if (text_is(sec, "grammar"))
                        gram = s->code;
+               else if (text_is(sec, "reduce"))
+                       pre_reduce = s->code;
                else {
                        fprintf(stderr, "Unknown content section: %.*s\n",
                                s->section.len, s->section.txt);
@@ -2394,7 +2407,7 @@ file with the code section (if any) and the parser tables and function.
                if (f) {
                        if (code)
                                code_node_print(f, code, infile);
-                       gen_parser(f, g, infile, name);
+                       gen_parser(f, g, infile, name, pre_reduce);
                        fclose(f);
                } else {
                        fprintf(stderr, "Cannot create %s.c\n",