#include <stdio.h>
#include <stdlib.h>

#define DEBUG_PARSER 1
#include "c.h"
#define DROP_SPECIAL_BITS ((1<<14)-1)
#define NEGATED_PHRASE (1<<15)
#define OPTIONAL_PHRASE (1<<14)


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

// const char *comment = "//\\\\ "; // for when we embed a grammar in a C file.
const char *comment = "";

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

  p = PHRASE_BASE;
  gp = 0;

  for (i = 0; i < MAX_BIP; i++) {
    fprintf(stdout, "B<%s> = %d;\n", phrasename[i], i);
  }
  
  for (;;) { // All phrases in grammar, sequentially
    alts = gram[gp];
    fprintf(stdout, "\n%sP<%s> = ", comment, 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%s  ", comment);

      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
    }
    p++;
    fprintf(stdout, "\n");
    if (p == (512+MAX_PHRASE)) break;
  }
  fprintf(stdout, "\n%sE\n", comment);
  exit(0);
}