create_parser.c

    // TO DO: Output //\\ B<...> = n;
    #include <stdio.h>
    #include <stdlib.h>

    #define DEBUG_PARSER 1
    #include "grammar.h"

    // Reconstitute grammar from tables.
    // Parsing code will be very similar, except recursing from PHRASE_BASE
    // rather than scanning sequentially from there.

    char *uline(char *s)
    {
      static char T[128];
      char *tp = T;
      int c;
      for (;;) {
        c = *s++;
        if (c == '-') c = '_';
        *tp++ = c;
        if (c == '\0') return T;
      }
    }

    #define DROP_SPECIAL_BITS ((1<<14)-1)
    #define NEGATED_PHRASE (1<<15)
    #define OPTIONAL_PHRASE (1<<14)

    int main(int argc, char **argv)
    {
      int p, i, gp, alts;

      p = PHRASE_BASE;
      gp = 0;

      for (;;) { // All phrases in grammar, sequentially
        int savegp = gp, savep = p;
        alts = gram[gp];
        fprintf(stdout, "\n \n//\\\\ P<%s> = ", phrasename[p-512]);
        gp++; // gp now points to first element (length) of first alt
        fflush(stdout);
        for (i = 0; i < alts; i++) {
          int each, phrases = gram[gp++];
          fprintf(stdout, "\n//\\\\   ");
          for (each = 0; each < phrases; each++) {
            int phrase = gram[gp] & DROP_SPECIAL_BITS;
    	int optional_phrase = gram[gp] & OPTIONAL_PHRASE;
            int negated_phrase = gram[gp] & NEGATED_PHRASE;
            if (phrase < 256) {
              fprintf(stdout, " '%c'", phrase);
            } else if (phrase < 512) {
              fprintf(stdout, " \"%s\"", keyword[phrase-256]);
            } else if (phrase < 512+MAX_BIP) {
              fprintf(stdout, " <");
              if (optional_phrase) fprintf(stdout, "?");
              if (negated_phrase) fprintf(stdout, "!");
    	  fprintf(stdout, "%s>", phrasename[phrase-512]);
            } else {
              fprintf(stdout, " <");
              if (optional_phrase) fprintf(stdout, "?");
              if (negated_phrase) fprintf(stdout, "!");
              fprintf(stdout, "%s>", phrasename[phrase-512]);
            }
            gp++; // move over element
            fflush(stdout);
          }
          if (i+1 < alts) fprintf(stdout, ","); else fprintf(stdout, ";");
          // gp now points to first element (length) of next alt, or start of next phrase
        }
        fprintf(stdout, "\n\n");

        gp = savegp; p = savep;
        alts = gram[gp];
        fprintf(stdout, "case P_%s:", uline(phrasename[p-512])/*, phrasename[p-512], p, alts*/);
        // fprintf(stdout, "(pi=%d gp=%d) ", phrase_starT[p-512-MAX_BIP], gp);
        gp++; // gp now points to first element (length) of first alt
        fflush(stdout);
        for (i = 0; i < alts; i++) {
          int each, phrases = gram[gp++], next;
          if (alts > 1) {
            if (i == 0) {
              fprintf(stdout, "\n  if (alt == %d)        {", i);
            } else if (i + 1 < alts) {
              fprintf(stdout, "\n  } else if (alt == %d) {", i);
            } else {
              fprintf(stdout, "\n  } else               {");
            }
          }
          next = 0;
          for (each = 0; each < phrases; each++) {
            int phrase = gram[gp] & DROP_SPECIAL_BITS;
    	int optional_phrase = gram[gp] & OPTIONAL_PHRASE;
            int negated_phrase = gram[gp] & NEGATED_PHRASE;
            fprintf(stdout, "\n  ");
            if (alts > 1) fprintf(stdout, "  ");
            if (phrase < 256) {
              fprintf(stdout, "T[%d] = lit('%c');", each+1, phrase);
            } else if (phrase < 512) {
              fprintf(stdout, "T[%d] = kw(/*\"%s\"*/ %d);", each+1, keyword[phrase-256], phrase-256);
            } else if (phrase < 512+MAX_BIP) {
              fprintf(stdout, "T[%d] = %s(ap+%d);", each+1, uline(phrasename[phrase-512]), next++);
            } else {
              if (negated_phrase || optional_phrase) {
                fprintf(stdout, "T[%d] = -1; // <%c%s>",
    		    each+1, (negated_phrase ? '!' : '?'), phrasename[phrase-512]); next += 1;
    	  } else {
                fprintf(stdout, "T[%d] = build_ast(A[ap+%d], depth+1); // <%s>",
                                each+1, next++, phrasename[phrase-512]);
    	  }
            }
            gp++; // move over element
            fflush(stdout);
          }

          if (alts == 0) {
            fprintf(stdout, "\n  return -1;\n  }\n\n");
          } else {
            if (alts > 1) {
              fprintf(stdout, "\n    T[0] = ");
            } else { // alts == 1
              fprintf(stdout, "\n  return ");
            }

            fprintf(stdout, "mktuple(phrase /*P_%s*/, alt /*%d*/, /*phrases*/ %d", uline(phrasename[p-512]), i+1, phrases);
            /*if (each)*/ fprintf(stdout, ", T /*");
            for (each = 0; each < phrases; each++) {
              fprintf(stdout, "T[%d]", each+1); if (each+1<phrases) fprintf(stdout, ", ");
            }
            fprintf(stdout, "*/);");
            // gp now points to first element (length) of next alt, or start of next phrase
            if (alts > 1) {
              if (i + 1 == alts) fprintf(stdout, "\n  }\n  return T[0];\n\n");
            } else fprintf(stdout, "\n");
          }
        }
        p++;
        fprintf(stdout, "\n");
        if (p == (512+MAX_PHRASE)) break;
      }

      exit(0);
    }