diff cgbigen/cgbigen.syn @ 0:13d2b8934445

Import AnaGram (near-)release tree into Mercurial.
author David A. Holland
date Sat, 22 Dec 2007 17:52:45 -0500
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgbigen/cgbigen.syn	Sat Dec 22 17:52:45 2007 -0500
@@ -0,0 +1,269 @@
+{
+/*
+ * AnaGram, a System for Syntax Directed Programming
+ * Copyright 1993 Parsifal Software. All Rights Reserved.
+ * Copyright 2006 David A. Holland. All Rights Reserved.
+ * See the file COPYING for license and usage terms.
+ *
+ * cgbigen.syn - Syntax for CG source file (cg46.cgs)
+ *               Generates cg46.h.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+}
+
+
+{
+
+static FILE *infile, *outfile;
+#define GET_INPUT  ((PCB).input_code = getc(infile))
+
+#define TEMPFILE ".cgstemp"
+
+//////////////////////////////
+
+#define STRBUFSIZE 32768
+static char strbuf[STRBUFSIZE];
+static size_t strbufpos = 0;
+
+static void addstr(int ch) {
+  if (strbufpos >= sizeof(strbuf)) {
+    fprintf(stderr, "compile-cgs: string buffer overflow; make it larger\n");
+    exit(1);
+  }
+  strbuf[strbufpos++] = ch;
+}
+
+static const char *getstr(void) {
+  addstr(0);
+  strbufpos = 0;
+  return strbuf;
+}
+
+//////////////////////////////
+
+/* remove a character from strbuf[] */
+static void strsnip(size_t pos) {
+  assert(pos < strbufpos);
+  strbufpos--;
+  memmove(strbuf+pos, strbuf+pos+1, strbufpos);
+}
+
+/* munge newlines in strbuf[]. for exact regression test compliance. */
+static void fudgenewlines(void) {
+  while (strbufpos > 0 && strbuf[0] == '\n') {
+    strsnip(0);
+  }
+  while (strbufpos > 1 && 
+	 strbuf[strbufpos-1] == '\n' && 
+	 strbuf[strbufpos-2] == '\n') {
+    strbufpos--;
+  }
+}
+
+//////////////////////////////
+
+static void emitstring(const char *s) {
+  size_t i, len;
+  unsigned pos = 0;
+
+  len = strlen(s);
+  if (len==0) {
+    fprintf(outfile, "  \"\"\n");
+    return;
+  }
+
+  for (i=0; i<len; i++) {
+    if (pos==0) {
+      fprintf(outfile, "  \"");
+    }
+    switch (s[i]) {
+      case '\r': if (pos==0) pos++; continue;
+      case '\n': fputs("\\n", outfile); pos+=3; break;
+      case '?': fputs("\\077", outfile); pos+=4; break;
+      case '"': fputs("\\\"", outfile); pos+=4; break;
+      case '\\': fputs("\\\\", outfile); pos+=4; break;
+      default:
+        if (s[i]>=32 && s[i]<127) {
+	  fputc(s[i], outfile);
+	  pos++;
+        }
+        else {
+          fprintf(outfile, "\\%03o", (unsigned)(unsigned char)s[i]);
+          pos+=4;
+        }
+	break;
+    }
+    if (pos>=72) {
+      fprintf(outfile, "\"\n");
+      pos = 0;
+    }
+  }
+  if (pos>0) {
+    fprintf(outfile, "\"\n");
+  }
+}
+
+//////////////////////////////
+
+static unsigned bodynum = 0, titlenum = 0;
+static int havetitle = 0;
+
+static void emitbody(const char *s) {
+  unsigned num;
+
+  num = bodynum;
+  bodynum = titlenum;
+  havetitle = 0;
+
+  fprintf(outfile, "static const char cgbody_%u[] =\n", num);
+  emitstring(s);
+  fprintf(outfile, ";\n");
+}
+
+static void emittitle(const char *s) {
+  unsigned num;
+
+  num = titlenum++;
+  if (havetitle) {
+    fprintf(outfile, "#define cgbody_%u cgbody_%u\n", num, bodynum);
+  }
+  else {
+    havetitle = 1;
+  }
+
+  fprintf(outfile, "static const char cgtitle_%u[] =\n", num);
+  emitstring(s);
+  fprintf(outfile, ";\n");
+}
+
+static void emittable(void) {
+  unsigned i;
+
+  assert(bodynum == titlenum);
+
+  fprintf(outfile, "struct cgentry {\n");
+  fprintf(outfile, "  const char *name;\n");
+  fprintf(outfile, "  const char *data;\n");
+  fprintf(outfile, "};\n\n");
+
+  fprintf(outfile, "static const unsigned cgtablenum = %u;\n", bodynum);
+  fprintf(outfile, "static struct cgentry cgtable[%u] = {\n", bodynum);
+  for (i=0; i<bodynum; i++) {
+    fprintf(outfile, "  { cgtitle_%u, cgbody_%u },\n", i, i);
+  }
+  fprintf(outfile, "};\n\n");
+}
+
+//////////////////////////////
+
+static void compile(const char *inpath, const char *outpath) {
+  infile = fopen(inpath, "rt");
+  if (!infile) {
+    fprintf(stderr, "compile-cgs: %s: %s\n", inpath, strerror(errno));
+    exit(1);
+  }
+
+  outfile = fopen(TEMPFILE, "wt");
+  if (!outfile) {
+    fprintf(stderr, "compile-cgs: %s: %s\n", TEMPFILE, strerror(errno));
+    exit(1);
+  }
+
+  fprintf(outfile, "/* Automatically generated; do not edit */\n\n");
+
+  cgbigen();
+  if (PCB.exit_flag != AG_SUCCESS_CODE) {
+    exit(1);
+  }
+
+  emittable();
+
+  fclose(outfile);
+  fclose(infile);
+
+  rename(TEMPFILE, outpath);
+}
+
+int main(int argc, char *argv[]) {
+  if (argc != 3) {
+    fprintf(stderr, "Usage: compile-cgs input-file output-file\n");
+    exit(1);
+  }
+
+  compile(argv[1], argv[2]);
+  return 0;
+}
+
+}
+
+[
+  default token type = void
+  //error trace
+  line numbers
+  line numbers path = "cgbigen.syn"
+]
+
+eof = -1
+range = 0..255
+blank = ' ' + '\t'
+cr = '\r'
+nl = '\n'
+textchar = range - cr - nl
+namechar = textchar - blank - ';' - ','
+
+//////////////////////////////
+
+(void) file $
+ -> blank lines?, block..., eof
+
+(void) block
+ -> title line,
+    body line?...,
+    "##", blank lines? = fudgenewlines(), emitbody(getstr());
+
+(void) title line
+ -> titles, comment?, newline
+
+//////////////////////////////
+
+(void) titles
+ -> title
+ -> titles, ',', blank?..., [comment?, newline, blank?...], title
+
+(void) title
+ -> name, blank?...  = emittitle(getstr());
+
+(void) name
+ -> namechar:c                      = addstr(c);
+ -> name, namechar:c                = addstr(c);
+ -> name, blank..., namechar:c      = addstr(' '), addstr(c);
+
+//////////////////////////////
+
+(void) body line
+ -> newline                   = addstr('\n');
+ -> text, newline             = addstr('\n');
+
+(void) text
+ -> textchar:c       = addstr(c);
+ -> text, textchar:c = addstr(c);
+
+//////////////////////////////
+
+(void) comment
+ -> {';' | "//"}, textchar...
+
+(void) newline
+ -> cr?, nl
+
+(void) blank lines
+ -> blank line...
+
+(void) blank line
+ -> blank?..., newline
+