Initial checkin of burg files
authorChris Lattner <sabre@nondot.org>
Tue, 17 Sep 2002 23:03:30 +0000 (23:03 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 17 Sep 2002 23:03:30 +0000 (23:03 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@3785 91177308-0d34-0410-b5e6-96231b3b80d8

60 files changed:
support/tools/Burg/COPYRIGHT [new file with mode: 0644]
support/tools/Burg/LOG_CHANGES [new file with mode: 0644]
support/tools/Burg/Makefile [new file with mode: 0644]
support/tools/Burg/README [new file with mode: 0644]
support/tools/Burg/b.h [new file with mode: 0644]
support/tools/Burg/be.c [new file with mode: 0644]
support/tools/Burg/burg.shar.gz [new file with mode: 0644]
support/tools/Burg/burs.c [new file with mode: 0644]
support/tools/Burg/closure.c [new file with mode: 0644]
support/tools/Burg/delta.c [new file with mode: 0644]
support/tools/Burg/fe.c [new file with mode: 0644]
support/tools/Burg/fe.h [new file with mode: 0644]
support/tools/Burg/gram.y [new file with mode: 0644]
support/tools/Burg/item.c [new file with mode: 0644]
support/tools/Burg/lex.c [new file with mode: 0644]
support/tools/Burg/list.c [new file with mode: 0644]
support/tools/Burg/main.c [new file with mode: 0644]
support/tools/Burg/map.c [new file with mode: 0644]
support/tools/Burg/nonterminal.c [new file with mode: 0644]
support/tools/Burg/operator.c [new file with mode: 0644]
support/tools/Burg/pattern.c [new file with mode: 0644]
support/tools/Burg/plank.c [new file with mode: 0644]
support/tools/Burg/queue.c [new file with mode: 0644]
support/tools/Burg/rule.c [new file with mode: 0644]
support/tools/Burg/sample.gr [new file with mode: 0644]
support/tools/Burg/string.c [new file with mode: 0644]
support/tools/Burg/symtab.c [new file with mode: 0644]
support/tools/Burg/table.c [new file with mode: 0644]
support/tools/Burg/trim.c [new file with mode: 0644]
support/tools/Burg/zalloc.c [new file with mode: 0644]
utils/Burg/COPYRIGHT [new file with mode: 0644]
utils/Burg/LOG_CHANGES [new file with mode: 0644]
utils/Burg/Makefile [new file with mode: 0644]
utils/Burg/README [new file with mode: 0644]
utils/Burg/b.h [new file with mode: 0644]
utils/Burg/be.c [new file with mode: 0644]
utils/Burg/burg.shar.gz [new file with mode: 0644]
utils/Burg/burs.c [new file with mode: 0644]
utils/Burg/closure.c [new file with mode: 0644]
utils/Burg/delta.c [new file with mode: 0644]
utils/Burg/fe.c [new file with mode: 0644]
utils/Burg/fe.h [new file with mode: 0644]
utils/Burg/gram.y [new file with mode: 0644]
utils/Burg/item.c [new file with mode: 0644]
utils/Burg/lex.c [new file with mode: 0644]
utils/Burg/list.c [new file with mode: 0644]
utils/Burg/main.c [new file with mode: 0644]
utils/Burg/map.c [new file with mode: 0644]
utils/Burg/nonterminal.c [new file with mode: 0644]
utils/Burg/operator.c [new file with mode: 0644]
utils/Burg/pattern.c [new file with mode: 0644]
utils/Burg/plank.c [new file with mode: 0644]
utils/Burg/queue.c [new file with mode: 0644]
utils/Burg/rule.c [new file with mode: 0644]
utils/Burg/sample.gr [new file with mode: 0644]
utils/Burg/string.c [new file with mode: 0644]
utils/Burg/symtab.c [new file with mode: 0644]
utils/Burg/table.c [new file with mode: 0644]
utils/Burg/trim.c [new file with mode: 0644]
utils/Burg/zalloc.c [new file with mode: 0644]

diff --git a/support/tools/Burg/COPYRIGHT b/support/tools/Burg/COPYRIGHT
new file mode 100644 (file)
index 0000000..1de0aad
--- /dev/null
@@ -0,0 +1,13 @@
+Copyright (C) 1991 Todd A. Proebsting
+All Rights Reserved.
+
+This software is in the public domain.  You may use and copy this material
+freely. This privilege extends to modifications, although any modified
+version of this system given to a third party should clearly identify your
+modifications as well as the original source.
+
+The responsibility for the use of this material resides entirely with you.
+We make no warranty of any kind concerning this material, nor do we make
+any claim as to the suitability of BURG for any application.  This software
+is experimental in nature and there is no written or implied warranty.  Use
+it at your own risk.
diff --git a/support/tools/Burg/LOG_CHANGES b/support/tools/Burg/LOG_CHANGES
new file mode 100644 (file)
index 0000000..a7ee343
--- /dev/null
@@ -0,0 +1,2 @@
+8/20/02 -- Vikram Adve
+       be.c: Replaced "char*" with "const char*" to avoid compiler warnings.
diff --git a/support/tools/Burg/Makefile b/support/tools/Burg/Makefile
new file mode 100644 (file)
index 0000000..226210d
--- /dev/null
@@ -0,0 +1,84 @@
+# $Id$
+
+#CFLAGS        =
+#CFLAGS        = -O
+#CFLAGS        = -O -DNOLEX
+CFLAGS = -g -DDEBUG
+#CFLAGS        = -g -DNOLEX -DDEBUG
+
+SRCS = \
+       be.c \
+       burs.c \
+       closure.c \
+       delta.c \
+       fe.c \
+       item.c \
+       lex.c \
+       list.c \
+       main.c \
+       map.c \
+       nonterminal.c \
+       operator.c \
+       pattern.c \
+       plank.c \
+       queue.c \
+       rule.c \
+       string.c \
+       symtab.c \
+       table.c \
+       trim.c \
+       zalloc.c
+
+BU_OBJS = \
+       burs.o \
+       closure.o \
+       delta.o \
+       item.o \
+       list.o \
+       map.o \
+       nonterminal.o \
+       operator.o \
+       pattern.o \
+       queue.o \
+       rule.o \
+       table.o \
+       trim.o \
+       zalloc.o
+
+FE_OBJS = \
+       be.o \
+       fe.o \
+       lex.o \
+       main.o \
+       plank.o \
+       string.o \
+       symtab.o \
+       y.tab.o
+
+all: test
+
+burg: $(BU_OBJS) $(FE_OBJS)
+       $(CC) -o burg $(CFLAGS) $(BU_OBJS) $(FE_OBJS)
+
+y.tab.c y.tab.h: gram.y
+       yacc -d gram.y
+
+clean:
+       rm -f *.o y.tab.h y.tab.c core burg *.aux *.log *.dvi sample sample.c tmp
+
+$(FE_OBJS):    b.h
+$(BU_OBJS):    b.h
+$(FE_OBJS):    fe.h
+
+lex.o: y.tab.h
+
+doc.dvi: doc.tex
+       latex doc; latex doc
+
+test: burg sample.gr
+       ./burg -I     <sample.gr   >sample.c && cc $(CFLAGS) -o sample sample.c && ./sample
+       ./burg -I      sample.gr   >tmp && cmp tmp sample.c
+       ./burg -I     <sample.gr -o tmp && cmp tmp sample.c
+       ./burg -I      sample.gr -o tmp && cmp tmp sample.c
+       ./burg -I -O0 <sample.gr   >tmp && cmp tmp sample.c
+       ./burg -I -=  <sample.gr   >tmp && cmp tmp sample.c
diff --git a/support/tools/Burg/README b/support/tools/Burg/README
new file mode 100644 (file)
index 0000000..bc26405
--- /dev/null
@@ -0,0 +1,14 @@
+To format the documentation, type "make doc.dvi" and print the result.
+
+The length of the cost vectors is fixed at 4 for reasons that are
+primarily historical.  To change it, edit the definition of DELTAWIDTH
+in b.h.
+
+Burg is compiled without optimization by default to avoid problems
+with initial installation.  To improve burg's performance, add '-O' to
+CFLAGS in the Makefile and rebuild burg with a high quality optimizing
+compiler.
+
+To be added to the Burg mailing list, send your preferred electronic
+mail address to cwf@research.att.com.
+
diff --git a/support/tools/Burg/b.h b/support/tools/Burg/b.h
new file mode 100644 (file)
index 0000000..f1b33ed
--- /dev/null
@@ -0,0 +1,311 @@
+/* $Id$ */
+
+#define MAX_ARITY      2
+
+typedef int ItemSetNum;
+typedef int OperatorNum;
+typedef int NonTerminalNum;
+typedef int RuleNum;
+typedef int ArityNum;
+typedef int ERuleNum;
+
+extern NonTerminalNum  last_user_nonterminal;
+extern NonTerminalNum  max_nonterminal;
+extern RuleNum         max_rule;
+extern ERuleNum                max_erule_num;
+extern int             max_arity;
+
+#ifdef __STDC__
+#define ARGS(x) x
+#else
+#define ARGS(x) ()
+#endif
+
+#ifndef NOLEX
+#define DELTAWIDTH     4
+typedef short DeltaCost[DELTAWIDTH];
+typedef short *DeltaPtr;
+extern void ASSIGNCOST ARGS((DeltaPtr, DeltaPtr));
+extern void ADDCOST ARGS((DeltaPtr, DeltaPtr));
+extern void MINUSCOST ARGS((DeltaPtr, DeltaPtr));
+extern void ZEROCOST ARGS((DeltaPtr));
+extern int LESSCOST ARGS((DeltaPtr, DeltaPtr));
+extern int EQUALCOST ARGS((DeltaPtr, DeltaPtr));
+#define PRINCIPLECOST(x)       (x[0])
+#else
+#define DELTAWIDTH     1
+typedef int DeltaCost;
+typedef int DeltaPtr;
+#define ASSIGNCOST(l, r)       ((l) = (r))
+#define ADDCOST(l, r)          ((l) += (r))
+#define MINUSCOST(l, r)                ((l) -= (r))
+#define ZEROCOST(x)            ((x) = 0)
+#define LESSCOST(l, r)         ((l) < (r))
+#define EQUALCOST(l, r)                ((l) == (r))
+#define PRINCIPLECOST(x)       (x)
+#endif /* NOLEX */
+#define NODIVERGE(c,state,nt,base)             if (prevent_divergence > 0) CHECKDIVERGE(c,state,nt,base);
+
+struct list {
+       void            *x;
+       struct list     *next;
+};
+typedef struct list    *List;
+
+struct intlist {
+       int             x;
+       struct intlist  *next;
+};
+typedef struct intlist *IntList;
+
+struct operator {
+       char            *name;
+       unsigned int    ref:1;
+       OperatorNum     num;
+       ItemSetNum      baseNum;
+       ItemSetNum      stateCount;
+       ArityNum        arity;
+       struct table    *table;
+};
+typedef struct operator        *Operator;
+
+struct nonterminal {
+       char            *name;
+       NonTerminalNum  num;
+       ItemSetNum      baseNum;
+       ItemSetNum      ruleCount;
+       struct plankMap *pmap;
+
+       struct rule     *sampleRule; /* diagnostic---gives "a" rule that with this lhs */
+};
+typedef struct nonterminal     *NonTerminal;
+
+struct pattern {
+       NonTerminal     normalizer;
+       Operator        op;             /* NULL if NonTerm -> NonTerm */
+       NonTerminal     children[MAX_ARITY];
+};
+typedef struct pattern *Pattern;
+
+struct rule {
+       DeltaCost       delta;
+       ERuleNum        erulenum;
+       RuleNum         num;
+       RuleNum         newNum;
+       NonTerminal     lhs;
+       Pattern         pat;
+       unsigned int    used:1;
+};
+typedef struct rule    *Rule;
+
+struct item {
+       DeltaCost       delta;
+       Rule            rule;
+};
+typedef struct item    Item;
+
+typedef short  *Relevant;      /* relevant non-terminals */
+
+typedef Item   *ItemArray;
+
+struct item_set {      /* indexed by NonTerminal */
+       ItemSetNum      num;
+       ItemSetNum      newNum;
+       Operator        op;
+       struct item_set *kids[2];
+       struct item_set *representative;
+       Relevant        relevant;
+       ItemArray       virgin;
+       ItemArray       closed;
+};
+typedef struct item_set        *Item_Set;
+
+#define DIM_MAP_SIZE   (1 << 8)
+#define GLOBAL_MAP_SIZE        (1 << 15)
+
+struct mapping {       /* should be a hash table for TS -> int */
+       List            *hash;
+       int             hash_size;
+       int             max_size;
+       ItemSetNum      count;
+       Item_Set        *set;   /* map: int <-> Item_Set */
+};
+typedef struct mapping *Mapping;
+
+struct index_map {
+       ItemSetNum      max_size;
+       Item_Set        *class;
+};
+typedef struct index_map       Index_Map;
+
+struct dimension {
+       Relevant        relevant;
+       Index_Map       index_map;
+       Mapping         map;
+       ItemSetNum      max_size;
+       struct plankMap *pmap;
+};
+typedef struct dimension       *Dimension;
+
+
+struct table {
+       Operator        op;
+       List            rules;
+       Relevant        relevant;
+       Dimension       dimen[MAX_ARITY];       /* 1 for each dimension */
+       Item_Set        *transition;    /* maps local indices to global
+                                               itemsets */
+};
+typedef struct table   *Table;
+
+struct relation {
+       Rule    rule;
+       DeltaCost       chain;
+       NonTerminalNum  nextchain;
+       DeltaCost       sibling;
+       int             sibFlag;
+       int             sibComputed;
+};
+typedef struct relation        *Relation;
+
+struct queue {
+       List head;
+       List tail;
+};
+typedef struct queue   *Queue;
+
+struct plank {
+       char *name;
+       List fields;
+       int width;
+};
+typedef struct plank   *Plank;
+
+struct except {
+       short index;
+       short value;
+};
+typedef struct except  *Exception;
+
+struct plankMap {
+       List exceptions;
+       int offset;
+       struct stateMap *values;
+};
+typedef struct plankMap        *PlankMap;
+
+struct stateMap {
+       char *fieldname;
+       Plank plank;
+       int width;
+       short *value;
+};
+typedef struct stateMap        *StateMap;
+
+struct stateMapTable {
+       List maps;
+};
+
+extern void CHECKDIVERGE ARGS((DeltaPtr, Item_Set, int, int));
+extern void zero ARGS((Item_Set));
+extern ItemArray newItemArray ARGS((void));
+extern ItemArray itemArrayCopy ARGS((ItemArray));
+extern Item_Set newItem_Set ARGS((Relevant));
+extern void freeItem_Set ARGS((Item_Set));
+extern Mapping newMapping ARGS((int));
+extern NonTerminal newNonTerminal ARGS((char *));
+extern int nonTerminalName ARGS((char *, int));
+extern Operator newOperator ARGS((char *, OperatorNum, ArityNum));
+extern Pattern newPattern ARGS((Operator));
+extern Rule newRule ARGS((DeltaPtr, ERuleNum, NonTerminal, Pattern));
+extern List newList ARGS((void *, List));
+extern IntList newIntList ARGS((int, IntList));
+extern int length ARGS((List));
+extern List appendList ARGS((void *, List));
+extern Table newTable ARGS((Operator));
+extern Queue newQ ARGS((void));
+extern void addQ ARGS((Queue, Item_Set));
+extern Item_Set popQ ARGS((Queue));
+extern int equivSet ARGS((Item_Set, Item_Set));
+extern Item_Set decode ARGS((Mapping, ItemSetNum));
+extern Item_Set encode ARGS((Mapping, Item_Set, int *));
+extern void build ARGS((void));
+extern Item_Set *transLval ARGS((Table, int, int));
+
+typedef void * (*ListFn) ARGS((void *));
+extern void foreachList ARGS((ListFn, List));
+extern void reveachList ARGS((ListFn, List));
+
+extern void addToTable ARGS((Table, Item_Set));
+
+extern void closure ARGS((Item_Set));
+extern void trim ARGS((Item_Set));
+extern void findChainRules ARGS((void));
+extern void findAllPairs ARGS((void));
+extern void addRelevant ARGS((Relevant, NonTerminalNum));
+
+extern void *zalloc ARGS((unsigned int));
+extern void zfree ARGS((void *));
+
+extern NonTerminal     start;
+extern List            rules;
+extern List            chainrules;
+extern List            operators;
+extern List            leaves;
+extern List            nonterminals;
+extern List            grammarNts;
+extern Queue           globalQ;
+extern Mapping         globalMap;
+extern int             exceptionTolerance;
+extern int             prevent_divergence;
+extern int             principleCost;
+extern int             lexical;
+extern struct rule     stub_rule;
+extern Relation        *allpairs;
+extern Item_Set                *sortedStates;
+extern Item_Set                errorState;
+
+extern void dumpRelevant ARGS((Relevant));
+extern void dumpOperator ARGS((Operator, int));
+extern void dumpOperator_s ARGS((Operator));
+extern void dumpOperator_l ARGS((Operator));
+extern void dumpNonTerminal ARGS((NonTerminal));
+extern void dumpRule ARGS((Rule));
+extern void dumpRuleList ARGS((List));
+extern void dumpItem ARGS((Item *));
+extern void dumpItem_Set ARGS((Item_Set));
+extern void dumpMapping ARGS((Mapping));
+extern void dumpQ ARGS((Queue));
+extern void dumpIndex_Map ARGS((Index_Map *));
+extern void dumpDimension ARGS((Dimension));
+extern void dumpPattern ARGS((Pattern));
+extern void dumpTable ARGS((Table, int));
+extern void dumpTransition ARGS((Table));
+extern void dumpCost ARGS((DeltaCost));
+extern void dumpAllPairs ARGS((void));
+extern void dumpRelation ARGS((Relation));
+extern void dumpSortedStates ARGS((void));
+extern void dumpSortedRules ARGS((void));
+extern int debugTrim;
+
+#ifdef DEBUG
+#define debug(a,b)     if (a) b
+#else
+#define debug(a,b)
+#endif
+extern int debugTables;
+
+#define TABLE_INCR     8
+#define STATES_INCR    64
+
+#ifdef NDEBUG
+#define assert(c) ((void) 0)
+#else
+#define assert(c) ((void) ((c) || fatal(__FILE__,__LINE__)))
+#endif
+
+extern void doStart ARGS((char *));
+extern void exit ARGS((int));
+extern int fatal ARGS((char *, int));
+extern void yyerror ARGS((char *));
+extern void yyerror1 ARGS((char *));
diff --git a/support/tools/Burg/be.c b/support/tools/Burg/be.c
new file mode 100644 (file)
index 0000000..e7feab8
--- /dev/null
@@ -0,0 +1,1052 @@
+char rcsid_be[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+#include "fe.h"
+
+#define ERROR_VAL 0
+
+FILE *outfile;
+char *prefix = "burm";
+
+static void doKids ARGS((RuleAST));
+static void doLabel ARGS((Operator));
+static void doLayout ARGS((RuleAST));
+static void doMakeTable ARGS((Operator));
+static void doVector ARGS((RuleAST));
+static void layoutNts ARGS((PatternAST));
+static void makeIndex_Map ARGS((Dimension));
+static void makePvector ARGS((void));
+static void makeState ARGS((void));
+static void printPatternAST ARGS((PatternAST));
+static void printPatternAST_int ARGS((PatternAST));
+static void setVectors ARGS((PatternAST));
+static void trailing_zeroes ARGS((int));
+static int seminal ARGS((int from, int to));
+static void printRule ARGS((RuleAST, char *));
+
+static void
+doLabel(op) Operator op;
+{
+       fprintf(outfile, "\tcase %d:\n", op->num);
+
+       switch (op->arity) {
+       default:
+               assert(0);
+               break;
+       case 0:
+               fprintf(outfile, "\t\treturn %d;\n", op->table->transition[0]->num);
+               break;
+       case 1:
+               if (op->table->rules) {
+                       fprintf(outfile, "\t\treturn %s_%s_transition[l];\n", prefix, op->name);
+               } else {
+                       fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL);
+               }
+               break;
+       case 2:
+               if (op->table->rules) {
+                       fprintf(outfile, "\t\treturn %s_%s_transition[%s_%s_imap_1[l]][%s_%s_imap_2[r]];\n", prefix, op->name, prefix, op->name, prefix, op->name);
+               } else {
+                       fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL);
+               }
+               break;
+       }
+}
+
+int
+opsOfArity(arity) int arity;
+{
+       int c;
+       List l;
+
+       c = 0;
+       for (l = operators; l; l = l->next) {
+               Operator op = (Operator) l->x;
+               if (op->arity == arity) {
+                       fprintf(outfile, "\tcase %d:\n", op->num);
+                       c++;
+               }
+       }
+       return c;
+}
+
+static void
+trailing_zeroes(z) int z;
+{
+       int i;
+
+       for (i = 0; i < z; i++) {
+               fprintf(outfile, ", 0");
+       }
+}
+
+void
+makeLabel()
+{
+       int flag;
+
+       fprintf(outfile, "#ifdef __STDC__\n");
+       fprintf(outfile, "int %s_label(%s_NODEPTR_TYPE n) {\n", prefix, prefix);
+       fprintf(outfile, "#else\n");
+       fprintf(outfile, "int %s_label(n) %s_NODEPTR_TYPE n; {\n", prefix, prefix);
+       fprintf(outfile, "#endif\n");
+
+       fprintf(outfile, 
+       "\t%s_assert(n, %s_PANIC(\"NULL pointer passed to %s_label\\n\"));\n",
+                               prefix, prefix, prefix);
+       fprintf(outfile, "\tswitch (%s_OP_LABEL(n)) {\n", prefix);
+       fprintf(outfile, "\tdefault: %s_PANIC(\"Bad op %%d in %s_label\\n\", %s_OP_LABEL(n)); abort(); return 0;\n", 
+                       prefix, prefix, prefix);
+
+       flag = opsOfArity(0);
+       if (flag > 0) {
+               fprintf(outfile, "\t\treturn %s_STATE_LABEL(n) = %s_state(%s_OP_LABEL(n)",
+                                       prefix, prefix, prefix);
+               trailing_zeroes(max_arity);
+               fprintf(outfile, ");\n");
+       }
+       flag = opsOfArity(1);
+       if (flag > 0) {
+               fprintf(outfile, "\t\treturn %s_STATE_LABEL(n) = %s_state(%s_OP_LABEL(n), %s_label(%s_LEFT_CHILD(n))",
+                                       prefix, prefix, prefix, prefix, prefix);
+               trailing_zeroes(max_arity-1);
+               fprintf(outfile, ");\n");
+       }
+       flag = opsOfArity(2);
+       if (flag > 0) {
+               fprintf(outfile, "\t\treturn %s_STATE_LABEL(n) = %s_state(%s_OP_LABEL(n), %s_label(%s_LEFT_CHILD(n)), %s_label(%s_RIGHT_CHILD(n))",
+                                       prefix, prefix, prefix, prefix, prefix, prefix, prefix);
+               trailing_zeroes(max_arity-2);
+               fprintf(outfile, ");\n");
+
+       }
+       fprintf(outfile, "\t}\n");
+       fprintf(outfile, "}\n");
+}
+
+static void
+makeState()
+{
+       fprintf(outfile, "int %s_state(int op, int l, int r) {\n", prefix);
+       fprintf(outfile, 
+       "\t%s_assert(l >= 0 && l < %d, PANIC(\"Bad state %%d passed to %s_state\\n\", l));\n",
+                               prefix, globalMap->count, prefix);
+       fprintf(outfile, 
+       "\t%s_assert(r >= 0 && r < %d, PANIC(\"Bad state %%d passed to %s_state\\n\", r));\n",
+                               prefix, globalMap->count, prefix);
+       fprintf(outfile, "\tswitch (op) {\n");
+       fprintf(outfile, "\tdefault: %s_PANIC(\"Bad op %%d in %s_state\\n\", op); abort(); return 0;\n", prefix, prefix);
+
+       foreachList((ListFn) doLabel, operators);
+
+       fprintf(outfile, "\t}\n");
+       fprintf(outfile, "}\n");
+}
+
+static char cumBuf[4000];
+static int vecIndex;
+char vecBuf[4000];
+
+static void
+setVectors(ast) PatternAST ast;
+{
+       char old[4000];
+
+       switch (ast->sym->tag) {
+       default:
+               assert(0);
+               break;
+       case NONTERMINAL:
+               sprintf(old, "\t\tkids[%d] = %s;\n", vecIndex, vecBuf);
+               strcat(cumBuf, old);
+               vecIndex++;
+               return;
+       case OPERATOR:
+               switch (ast->sym->u.op->arity) {
+               default:
+                       assert(0);
+                       break;
+               case 0:
+                       return;
+               case 1:
+                       strcpy(old, vecBuf);
+                       sprintf(vecBuf, "%s_LEFT_CHILD(%s)", prefix, old);
+                       setVectors((PatternAST) ast->children->x);
+                       strcpy(vecBuf, old);
+                       return;
+               case 2:
+                       strcpy(old, vecBuf);
+                       sprintf(vecBuf, "%s_LEFT_CHILD(%s)", prefix, old);
+                       setVectors((PatternAST) ast->children->x);
+
+                       sprintf(vecBuf, "%s_RIGHT_CHILD(%s)", prefix, old);
+                       setVectors((PatternAST) ast->children->next->x);
+                       strcpy(vecBuf, old);
+                       return;
+               }
+               break;
+       }
+}
+
+#define MAX_VECTOR     10
+
+void
+makeRuleTable()
+{
+       int s,nt;
+
+       fprintf(outfile, "static short %s_RuleNo[%d][%d] = {\n", prefix, globalMap->count, last_user_nonterminal-1);
+       for (s = 0; s < globalMap->count; s++) {
+               Item_Set ts = globalMap->set[s];
+               if (s > 0) {
+                       fprintf(outfile, ",\n");
+               }
+               fprintf(outfile, "/* state %d */\n", s);
+               fprintf(outfile, "{");
+               for (nt = 1; nt < last_user_nonterminal; nt++) {
+                       if (nt > 1) {
+                               fprintf(outfile, ",");
+                               if (nt % 10 == 1) {
+                                       fprintf(outfile, "\t/* state %d; Nonterminals %d-%d */\n", s, nt-10, nt-1);
+                               }
+                       }
+                       if (ts->closed[nt].rule) {
+                               ts->closed[nt].rule->used = 1;
+                               fprintf(outfile, "%5d", ts->closed[nt].rule->erulenum);
+                       } else {
+                               fprintf(outfile, "%5d", ERROR_VAL);
+                       }
+               }
+               fprintf(outfile, "}");
+       }
+       fprintf(outfile, "};\n");
+}
+
+static void
+makeIndex_Map(d) Dimension d;
+{
+       int s;
+
+       for (s = 0; s < globalMap->count; s++) {
+               if (s > 0) {
+                       fprintf(outfile, ",");
+                       if (s % 10 == 0) {
+                               fprintf(outfile, "\t/* %d-%d */\n", s-10, s-1);
+                       }
+               }
+               fprintf(outfile, "%5d", d->map->set[d->index_map.class[s]->num]->num);
+       }
+       fprintf(outfile, "};\n");
+}
+
+static void
+doMakeTable(op) Operator op;
+{
+       int s;
+       int i,j;
+       Dimension d;
+
+       switch (op->arity) {
+       default:
+               assert(0);
+               break;
+       case 0:
+               return;
+       case 1:
+               if (!op->table->rules) {
+                       return;
+               }
+               d = op->table->dimen[0];
+               fprintf(outfile, "static short %s_%s_transition[%d] = {\n", prefix, op->name, globalMap->count);
+               for (s = 0; s < globalMap->count; s++) {
+                       if (s > 0) {
+                               fprintf(outfile, ", ");
+                               if (s % 10 == 0) {
+                                       fprintf(outfile, "\t/* %d-%d */\n", s-10, s-1);
+                               }
+                       }
+                       fprintf(outfile, "%5d", op->table->transition[d->map->set[d->index_map.class[s]->num]->num]->num);
+               }
+               fprintf(outfile, "};\n");
+               break;
+       case 2:
+               if (!op->table->rules) {
+                       return;
+               }
+               fprintf(outfile, "static short %s_%s_imap_1[%d] = {\n", prefix, op->name, globalMap->count);
+               makeIndex_Map(op->table->dimen[0]);
+               fprintf(outfile, "static short %s_%s_imap_2[%d] = {\n", prefix, op->name, globalMap->count);
+               makeIndex_Map(op->table->dimen[1]);
+
+               fprintf(outfile, "static short %s_%s_transition[%d][%d] = {", prefix, op->name,
+                                               op->table->dimen[0]->map->count,
+                                               op->table->dimen[1]->map->count);
+               for (i = 0; i < op->table->dimen[0]->map->count; i++) {
+                       if (i > 0) {
+                               fprintf(outfile, ",");
+                       }
+                       fprintf(outfile, "\n");
+                       fprintf(outfile, "{");
+                       for (j = 0; j < op->table->dimen[1]->map->count; j++) {
+                               Item_Set *ts = transLval(op->table, i, j);
+                               if (j > 0) {
+                                       fprintf(outfile, ",");
+                               }
+                               fprintf(outfile, "%5d", (*ts)->num);
+                       }
+                       fprintf(outfile, "}\t/* row %d */", i);
+               }
+               fprintf(outfile, "\n};\n");
+
+               break;
+       }
+}
+
+void
+makeTables()
+{
+       foreachList((ListFn) doMakeTable, operators);
+}
+
+RuleAST *pVector;
+
+void
+makeLHSmap()
+{
+       int i;
+
+       if (!pVector) {
+               makePvector();
+       }
+
+       fprintf(outfile, "short %s_lhs[] = {\n", prefix);
+       for (i = 0; i <= max_erule_num; i++) {
+               if (pVector[i]) {
+                       fprintf(outfile, "\t%s_%s_NT,\n", prefix, pVector[i]->lhs);
+               } else {
+                       fprintf(outfile, "\t0,\n");
+               }
+       }
+       fprintf(outfile, "};\n\n", prefix);
+}
+
+static int seminal(from, to)
+{
+       return allpairs[from][to].rule ? allpairs[from][to].rule->erulenum : 0;
+
+       /*
+       int tmp, last;
+       tmp = 0;
+       for (;;) {
+               last = tmp;
+               tmp = allpairs[to][from].rule ? allpairs[to][from].rule->erulenum : 0;
+               if (!tmp) {
+                       break;
+               }
+               assert(pVector[tmp]);
+               to = pVector[tmp]->rule->pat->children[0]->num;
+       }
+       return last;
+       */
+}
+
+void
+makeClosureArray()
+{
+       int i, j;
+
+       if (!pVector) {
+               makePvector();
+       }
+
+       fprintf(outfile, "short %s_closure[%d][%d] = {\n", prefix, last_user_nonterminal, last_user_nonterminal);
+       for (i = 0; i < last_user_nonterminal; i++) {
+               fprintf(outfile, "\t{");
+               for (j = 0; j < last_user_nonterminal; j++) {
+                       if (j > 0 && j%10 == 0) {
+                               fprintf(outfile, "\n\t ");
+                       }
+                       fprintf(outfile, " %4d,", seminal(i,j));
+               }
+               fprintf(outfile, "},\n");
+       }
+       fprintf(outfile, "};\n");
+}
+
+void
+makeCostVector(z,d) int z; DeltaCost d;
+{
+       fprintf(outfile, "\t{");
+#ifdef NOLEX
+       if (z) {
+               fprintf(outfile, "%5d", d);
+       } else {
+               fprintf(outfile, "%5d", 0);
+       }
+#else
+       {
+       int j;
+       for (j = 0; j < DELTAWIDTH; j++) {
+               if (j > 0) {
+                       fprintf(outfile, ",");
+               }
+               if (z) {
+                       fprintf(outfile, "%5d", d[j]);
+               } else {
+                       fprintf(outfile, "%5d", 0);
+               }
+       }
+       }
+#endif /* NOLEX */
+       fprintf(outfile, "}");
+}
+
+void
+makeCostArray()
+{
+       int i;
+
+       if (!pVector) {
+               makePvector();
+       }
+
+       fprintf(outfile, "short %s_cost[][%d] = {\n", prefix, DELTAWIDTH);
+       for (i = 0; i <= max_erule_num; i++) {
+               makeCostVector(pVector[i], pVector[i] ? pVector[i]->rule->delta : 0);
+               fprintf(outfile, ", /* ");
+               printRule(pVector[i], "(none)");
+               fprintf(outfile, " = %d */\n", i);
+       }
+       fprintf(outfile, "};\n");
+}
+
+void
+makeStateStringArray()
+{
+       int s;
+       int nt;
+       int states;
+       
+       states = globalMap->count;
+       fprintf(outfile, "\nconst char * %s_state_string[] = {\n", prefix);
+       fprintf(outfile, "\" not a state\", /* state 0 */\n");
+       for (s = 0; s < states-1; s++) {
+               fprintf(outfile, "\t\"");
+               printRepresentative(outfile, sortedStates[s]);
+               fprintf(outfile, "\", /* state #%d */\n", s+1);
+       }
+       fprintf(outfile, "};\n");
+}
+
+void
+makeDeltaCostArray()
+{
+       int s;
+       int nt;
+       int states;
+       
+       states = globalMap->count;
+       fprintf(outfile, "\nshort %s_delta_cost[%d][%d][%d] = {\n", prefix, states, last_user_nonterminal, DELTAWIDTH);
+       fprintf(outfile, "{{0}}, /* state 0 */\n");
+       for (s = 0; s < states-1; s++) {
+               fprintf(outfile, "{ /* state #%d: ", s+1);
+               printRepresentative(outfile, sortedStates[s]);
+               fprintf(outfile, " */\n", s+1);
+               fprintf(outfile, "\t{0},\n");
+               for (nt = 1; nt < last_user_nonterminal; nt++) {
+                       makeCostVector(1, sortedStates[s]->closed[nt].delta);
+                       fprintf(outfile, ", /* ");
+                       if (sortedStates[s]->closed[nt].rule) {
+                               int erulenum = sortedStates[s]->closed[nt].rule->erulenum;
+                               printRule(pVector[erulenum], "(none)");
+                               fprintf(outfile, " = %d */", erulenum);
+                       } else {
+                               fprintf(outfile, "(none) */");
+                       }
+                       fprintf(outfile, "\n");
+               }
+               fprintf(outfile, "},\n");
+       }
+       fprintf(outfile, "};\n");
+}
+
+static void
+printPatternAST_int(p) PatternAST p;
+{
+       List l;
+
+       if (p) {
+               switch (p->sym->tag) {
+               case NONTERMINAL:
+                       fprintf(outfile, "%5d,", -p->sym->u.nt->num);
+                       break;
+               case OPERATOR:
+                       fprintf(outfile, "%5d,", p->sym->u.op->num);
+                       break;
+               default:
+                       assert(0);
+               }
+               if (p->children) {
+                       for (l = p->children; l; l = l->next) {
+                               PatternAST pat = (PatternAST) l->x;
+                               printPatternAST_int(pat);
+                       }
+               }
+       }
+}
+
+static void
+printPatternAST(p) PatternAST p;
+{
+       List l;
+
+       if (p) {
+               fprintf(outfile, "%s", p->op);
+               if (p->children) {
+                       fprintf(outfile, "(");
+                       for (l = p->children; l; l = l->next) {
+                               PatternAST pat = (PatternAST) l->x;
+                               if (l != p->children) {
+                                       fprintf(outfile, ", ");
+                               }
+                               printPatternAST(pat);
+                       }
+                       fprintf(outfile, ")");
+               }
+       }
+}
+
+static void
+layoutNts(ast) PatternAST ast;
+{
+       char out[30];
+
+       switch (ast->sym->tag) {
+       default:
+               assert(0);
+               break;
+       case NONTERMINAL:
+               sprintf(out, "%d, ", ast->sym->u.nt->num);
+               strcat(cumBuf, out);
+               return;
+       case OPERATOR:
+               switch (ast->sym->u.op->arity) {
+               default:
+                       assert(0);
+                       break;
+               case 0:
+                       return;
+               case 1:
+                       layoutNts((PatternAST) ast->children->x);
+                       return;
+               case 2:
+                       layoutNts((PatternAST) ast->children->x);
+                       layoutNts((PatternAST) ast->children->next->x);
+                       return;
+               }
+               break;
+       }
+}
+
+static void
+doVector(ast) RuleAST ast;
+{
+       if (pVector[ast->rule->erulenum]) {
+               fprintf(stderr, "ERROR: non-unique external rule number: (%d)\n", ast->rule->erulenum);
+               exit(1);
+       }
+       pVector[ast->rule->erulenum] = ast;
+}
+
+static void
+makePvector()
+{
+       pVector = (RuleAST*) zalloc((max_erule_num+1) * sizeof(RuleAST));
+       foreachList((ListFn) doVector, ruleASTs);
+}
+
+static void
+doLayout(ast) RuleAST ast;
+{
+       sprintf(cumBuf, "{ ");
+       layoutNts(ast->pat);
+       strcat(cumBuf, "0 }");
+}
+
+void
+makeNts()
+{
+       int i;
+       int new;
+       StrTable nts;
+
+       nts = newStrTable();
+
+       if (!pVector) {
+               makePvector();
+       }
+
+       for (i = 0; i <= max_erule_num; i++) {
+               if (pVector[i]) {
+                       doLayout(pVector[i]);
+                       pVector[i]->nts = addString(nts, cumBuf, i, &new);
+                       if (new) {
+                               char ename[50];
+
+                               sprintf(ename, "%s_r%d_nts", prefix, i);
+                               pVector[i]->nts->ename = (char*) zalloc(strlen(ename)+1);
+                               strcpy(pVector[i]->nts->ename, ename);
+                               fprintf(outfile, "static short %s[] =", ename);
+                               fprintf(outfile, "%s;\n", cumBuf);
+                       }
+               }
+       }
+
+       fprintf(outfile, "short *%s_nts[] = {\n", prefix);
+       for (i = 0; i <= max_erule_num; i++) {
+               if (pVector[i]) {
+                       fprintf(outfile, "\t%s,\n", pVector[i]->nts->ename);
+               } else {
+                       fprintf(outfile, "\t0,\n");
+               }
+       }
+       fprintf(outfile, "};\n");
+}
+
+static void
+printRule(r,d) RuleAST r; char *d;
+{
+       if (r) {
+               fprintf(outfile, "%s: ", r->rule->lhs->name);
+               printPatternAST(r->pat);
+       } else {
+               fprintf(outfile, "%s", d);
+       }
+}
+
+void
+makeRuleDescArray()
+{
+       int i;
+
+       if (!pVector) {
+               makePvector();
+       }
+
+       if (last_user_nonterminal != max_nonterminal) {
+               /* not normal form */
+               fprintf(outfile, "short %s_rule_descriptor_0[] = { 0, 0 };\n", prefix);
+       } else {
+               fprintf(outfile, "short %s_rule_descriptor_0[] = { 0, 1 };\n", prefix);
+       }
+       for (i = 1; i <= max_erule_num; i++) {
+               if (pVector[i]) {
+                       Operator o;
+                       NonTerminal t;
+
+                       fprintf(outfile, "short %s_rule_descriptor_%d[] = {", prefix, i);
+                       fprintf(outfile, "%5d,", -pVector[i]->rule->lhs->num);
+                       printPatternAST_int(pVector[i]->pat);
+                       fprintf(outfile, " };\n");
+               }
+       }
+
+       fprintf(outfile, "/* %s_rule_descriptors[0][1] = 1 iff grammar is normal form. */\n", prefix);
+       fprintf(outfile, "short * %s_rule_descriptors[] = {\n", prefix);
+       fprintf(outfile, "\t%s_rule_descriptor_0,\n", prefix);
+       for (i = 1; i <= max_erule_num; i++) {
+               if (pVector[i]) {
+                       fprintf(outfile, "\t%s_rule_descriptor_%d,\n", prefix, i);
+               } else {
+                       fprintf(outfile, "\t%s_rule_descriptor_0,\n", prefix);
+               }
+       }
+       fprintf(outfile, "};\n");
+}
+
+
+void
+makeRuleDescArray2()
+{
+       int i;
+
+       if (!pVector) {
+               makePvector();
+       }
+
+       fprintf(outfile, "struct { int lhs, op, left, right; } %s_rule_struct[] = {\n", prefix);
+       if (last_user_nonterminal != max_nonterminal) {
+               /* not normal form */
+               fprintf(outfile, "\t{-1},");
+       } else {
+               fprintf(outfile, "\t{0},");
+       }
+       fprintf(outfile, " /* 0 if normal form, -1 if not normal form */\n");
+       for (i = 1; i <= max_erule_num; i++) {
+               fprintf(outfile, "\t");
+               if (pVector[i]) {
+                       Operator o;
+                       NonTerminal t;
+
+                       fprintf(outfile, "{");
+                       fprintf(outfile, "%5d, %5d, %5d, %5d",
+                               pVector[i]->rule->lhs->num,
+                               (o = pVector[i]->rule->pat->op) ? o->num : 0,
+                               (t = pVector[i]->rule->pat->children[0]) ? t->num : 0,
+                               (t = pVector[i]->rule->pat->children[1]) ? t->num : 0
+                               );
+                       fprintf(outfile, "} /* ");
+                       printRule(pVector[i], "0");
+                       fprintf(outfile, " = %d */", i);
+               } else {
+                       fprintf(outfile, "{0}");
+               }
+               fprintf(outfile, ",\n");
+       }
+       fprintf(outfile, "};\n");
+}
+
+void
+makeStringArray()
+{
+       int i;
+
+       if (!pVector) {
+               makePvector();
+       }
+
+       fprintf(outfile, "const char *%s_string[] = {\n", prefix);
+       for (i = 0; i <= max_erule_num; i++) {
+               fprintf(outfile, "\t");
+               if (pVector[i]) {
+                       fprintf(outfile, "\"");
+                       printRule(pVector[i], "0");
+                       fprintf(outfile, "\"");
+               } else {
+                       fprintf(outfile, "0");
+               }
+               fprintf(outfile, ",\n");
+       }
+       fprintf(outfile, "};\n");
+       fprintf(outfile, "int %s_max_rule = %d;\n", prefix, max_erule_num);
+       fprintf(outfile, "#define %s_Max_rule %d\n", prefix, max_erule_num);
+}
+
+void
+makeRule()
+{
+       fprintf(outfile, "int %s_rule(int state, int goalnt) {\n", prefix);
+       fprintf(outfile, 
+       "\t%s_assert(state >= 0 && state < %d, PANIC(\"Bad state %%d passed to %s_rule\\n\", state));\n",
+                               prefix, globalMap->count, prefix);
+       fprintf(outfile, 
+       "\t%s_assert(goalnt >= 1 && goalnt < %d, PANIC(\"Bad goalnt %%d passed to %s_rule\\n\", state));\n",
+                               prefix, max_nonterminal, prefix);
+       fprintf(outfile, "\treturn %s_RuleNo[state][goalnt-1];\n", prefix);
+       fprintf(outfile, "};\n");
+}
+
+static StrTable kids;
+
+static void
+doKids(ast) RuleAST ast;
+{
+       int new;
+
+       vecIndex = 0;
+       cumBuf[0] = 0;
+       strcpy(vecBuf, "p");
+       setVectors(ast->pat);
+
+       ast->kids = addString(kids, cumBuf, ast->rule->erulenum, &new);
+
+}
+
+void
+makeKids()
+{
+       List e;
+       IntList r;
+
+       kids = newStrTable();
+
+       fprintf(outfile, "#ifdef __STDC__\n");
+       fprintf(outfile, "%s_NODEPTR_TYPE * %s_kids(%s_NODEPTR_TYPE p, int rulenumber, %s_NODEPTR_TYPE *kids) {\n", prefix, prefix, prefix, prefix);
+       fprintf(outfile, "#else\n");
+       fprintf(outfile, "%s_NODEPTR_TYPE * %s_kids(p, rulenumber, kids) %s_NODEPTR_TYPE p; int rulenumber; %s_NODEPTR_TYPE *kids; {\n", prefix, prefix, prefix, prefix);
+       fprintf(outfile, "#endif\n");
+
+       fprintf(outfile, 
+       "\t%s_assert(p, %s_PANIC(\"NULL node pointer passed to %s_kids\\n\"));\n",
+                               prefix, prefix, prefix);
+       fprintf(outfile, 
+       "\t%s_assert(kids, %s_PANIC(\"NULL kids pointer passed to %s_kids\\n\"));\n",
+                               prefix, prefix, prefix);
+       fprintf(outfile, "\tswitch (rulenumber) {\n");
+       fprintf(outfile, "\tdefault:\n");
+       fprintf(outfile, "\t\t%s_PANIC(\"Unknown Rule %%d in %s_kids;\\n\", rulenumber);\n", prefix, prefix);
+       fprintf(outfile, "\t\tabort();\n");
+       fprintf(outfile, "\t\t/* NOTREACHED */\n");
+
+       foreachList((ListFn) doKids, ruleASTs);
+
+       for (e = kids->elems; e; e = e->next) {
+               StrTableElement el = (StrTableElement) e->x;
+               for (r = el->erulenos; r; r = r->next) {
+                       int i = r->x;
+                       fprintf(outfile, "\tcase %d:\n", i);
+               }
+               fprintf(outfile, "%s", el->str);
+               fprintf(outfile, "\t\tbreak;\n");
+       }
+       fprintf(outfile, "\t}\n");
+       fprintf(outfile, "\treturn kids;\n");
+       fprintf(outfile, "}\n");
+}
+
+void
+makeOpLabel()
+{
+       fprintf(outfile, "#ifdef __STDC__\n");
+       fprintf(outfile, "int %s_op_label(%s_NODEPTR_TYPE p) {\n", prefix, prefix);
+       fprintf(outfile, "#else\n");
+       fprintf(outfile, "int %s_op_label(p) %s_NODEPTR_TYPE p; {\n", prefix, prefix);
+       fprintf(outfile, "#endif\n");
+       fprintf(outfile, 
+       "\t%s_assert(p, %s_PANIC(\"NULL pointer passed to %s_op_label\\n\"));\n",
+                               prefix, prefix, prefix);
+       fprintf(outfile, "\treturn %s_OP_LABEL(p);\n", prefix);
+       fprintf(outfile, "}\n");
+}
+
+void
+makeStateLabel()
+{
+       fprintf(outfile, "#ifdef __STDC__\n");
+       fprintf(outfile, "int %s_state_label(%s_NODEPTR_TYPE p) {\n", prefix, prefix);
+       fprintf(outfile, "#else\n");
+       fprintf(outfile, "int %s_state_label(p) %s_NODEPTR_TYPE p; {\n", prefix, prefix);
+       fprintf(outfile, "#endif\n");
+
+       fprintf(outfile, 
+       "\t%s_assert(p, %s_PANIC(\"NULL pointer passed to %s_state_label\\n\"));\n",
+                               prefix, prefix, prefix);
+       fprintf(outfile, "\treturn %s_STATE_LABEL(p);\n", prefix);
+       fprintf(outfile, "}\n");
+}
+
+void
+makeChild()
+{
+       fprintf(outfile, "#ifdef __STDC__\n");
+       fprintf(outfile, "%s_NODEPTR_TYPE %s_child(%s_NODEPTR_TYPE p, int index) {\n", prefix, prefix, prefix);
+       fprintf(outfile, "#else\n");
+       fprintf(outfile, "%s_NODEPTR_TYPE %s_child(p, index) %s_NODEPTR_TYPE p; int index; {\n", prefix, prefix, prefix);
+       fprintf(outfile, "#endif\n");
+
+       fprintf(outfile, 
+       "\t%s_assert(p, %s_PANIC(\"NULL pointer passed to %s_child\\n\"));\n",
+                               prefix, prefix, prefix);
+       fprintf(outfile, "\tswitch (index) {\n");
+       fprintf(outfile, "\tcase 0:\n");
+       fprintf(outfile, "\t\treturn %s_LEFT_CHILD(p);\n", prefix);
+       fprintf(outfile, "\tcase 1:\n");
+       fprintf(outfile, "\t\treturn %s_RIGHT_CHILD(p);\n", prefix);
+       fprintf(outfile, "\t}\n");
+       fprintf(outfile, "\t%s_PANIC(\"Bad index %%d in %s_child;\\n\", index);\n", prefix, prefix);
+       fprintf(outfile, "\tabort();\n");
+       fprintf(outfile, "\treturn 0;\n");
+       fprintf(outfile, "}\n");
+}
+
+static Operator *opVector;
+static int maxOperator;
+
+void
+makeOperatorVector()
+{
+       List l;
+
+       maxOperator = 0;
+       for (l = operators; l; l = l->next) {
+               Operator op = (Operator) l->x;
+               if (op->num > maxOperator) {
+                       maxOperator = op->num;
+               }
+       }
+       opVector = (Operator*) zalloc((maxOperator+1) * sizeof(*opVector));
+       for (l = operators; l; l = l->next) {
+               Operator op = (Operator) l->x;
+               if (opVector[op->num]) {
+                       fprintf(stderr, "ERROR: Non-unique external symbol number (%d)\n", op->num);
+                       exit(1);
+               }
+               opVector[op->num] = op;
+       }
+}
+
+void
+makeOperators()
+{
+       int i;
+
+       if (!opVector) {
+               makeOperatorVector();
+       }
+       fprintf(outfile, "const char * %s_opname[] = {\n", prefix);
+       for (i = 0; i <= maxOperator; i++) {
+               if (i > 0) {
+                       fprintf(outfile, ", /* %d */\n", i-1);
+               }
+               if (opVector[i]) {
+                       fprintf(outfile, "\t\"%s\"", opVector[i]->name);
+               } else {
+                       fprintf(outfile, "\t0");
+               }
+       }
+       fprintf(outfile, "\n};\n");
+       fprintf(outfile, "char %s_arity[] = {\n", prefix);
+       for (i = 0; i <= maxOperator; i++) {
+               if (i > 0) {
+                       fprintf(outfile, ", /* %d */\n", i-1);
+               }
+               fprintf(outfile, "\t%d", opVector[i] ? opVector[i]->arity : -1);
+       }
+       fprintf(outfile, "\n};\n");
+       fprintf(outfile, "int %s_max_op = %d;\n", prefix, maxOperator);
+       fprintf(outfile, "int %s_max_state = %d;\n", prefix, globalMap->count-1);
+       fprintf(outfile, "#define %s_Max_state %d\n", prefix, globalMap->count-1);
+}
+
+void
+makeDebug()
+{
+       fprintf(outfile, "#ifdef DEBUG\n");
+       fprintf(outfile, "int %s_debug;\n", prefix);
+       fprintf(outfile, "#endif /* DEBUG */\n");
+}
+
+void
+makeSimple()
+{
+       makeRuleTable();
+       makeTables();
+       makeRule();
+       makeState();
+}
+
+void
+startOptional()
+{
+       fprintf(outfile, "#ifdef %s_STATE_LABEL\n", prefix);
+       fprintf(outfile, "#define %s_INCLUDE_EXTRA\n", prefix);
+       fprintf(outfile, "#else\n");
+       fprintf(outfile, "#ifdef STATE_LABEL\n");
+       fprintf(outfile, "#define %s_INCLUDE_EXTRA\n", prefix);
+       fprintf(outfile, "#define %s_STATE_LABEL \tSTATE_LABEL\n", prefix);
+       fprintf(outfile, "#define %s_NODEPTR_TYPE\tNODEPTR_TYPE\n", prefix);
+       fprintf(outfile, "#define %s_LEFT_CHILD  \tLEFT_CHILD\n", prefix);
+       fprintf(outfile, "#define %s_OP_LABEL    \tOP_LABEL\n", prefix);
+       fprintf(outfile, "#define %s_RIGHT_CHILD \tRIGHT_CHILD\n", prefix);
+       fprintf(outfile, "#endif /* STATE_LABEL */\n");
+       fprintf(outfile, "#endif /* %s_STATE_LABEL */\n\n", prefix);
+
+       fprintf(outfile, "#ifdef %s_INCLUDE_EXTRA\n\n", prefix);
+
+}
+
+void
+makeNonterminals()
+{
+       List l;
+
+       for (l = nonterminals; l; l = l->next) {
+               NonTerminal nt = (NonTerminal) l->x;
+               if (nt->num < last_user_nonterminal) {
+                       fprintf(outfile, "#define %s_%s_NT %d\n", prefix, nt->name, nt->num);
+               }
+       }
+       fprintf(outfile, "#define %s_NT %d\n", prefix, last_user_nonterminal-1);
+}
+
+void
+makeNonterminalArray()
+{
+       int i;
+       List l;
+       NonTerminal *nta;
+
+       nta = (NonTerminal *) zalloc(sizeof(*nta) * last_user_nonterminal);
+
+       for (l = nonterminals; l; l = l->next) {
+               NonTerminal nt = (NonTerminal) l->x;
+               if (nt->num < last_user_nonterminal) {
+                       nta[nt->num] = nt;
+               }
+       }
+
+       fprintf(outfile, "const char *%s_ntname[] = {\n", prefix);
+       fprintf(outfile, "\t\"Error: Nonterminals are > 0\",\n");
+       for (i = 1; i < last_user_nonterminal; i++) {
+               fprintf(outfile, "\t\"%s\",\n", nta[i]->name);
+       }
+       fprintf(outfile, "\t0\n");
+       fprintf(outfile, "};\n\n");
+
+       zfree(nta);
+}
+
+void
+endOptional()
+{
+       fprintf(outfile, "#endif /* %s_INCLUDE_EXTRA */\n", prefix);
+}
+
+void
+startBurm()
+{
+       fprintf(outfile, "#ifndef %s_PANIC\n", prefix);
+       fprintf(outfile, "#define %s_PANIC\tPANIC\n", prefix);
+       fprintf(outfile, "#endif /* %s_PANIC */\n", prefix);
+       fprintf(outfile, "#ifdef __STDC__\n");
+       fprintf(outfile, "extern void abort(void);\n");
+       fprintf(outfile, "#else\n");
+       fprintf(outfile, "extern void abort();\n");
+       fprintf(outfile, "#endif\n");
+       fprintf(outfile, "#ifdef NDEBUG\n");
+       fprintf(outfile, "#define %s_assert(x,y)\t;\n", prefix);
+       fprintf(outfile, "#else\n");
+       fprintf(outfile, "#define %s_assert(x,y)\tif(!(x)) {y; abort();}\n", prefix);
+       fprintf(outfile, "#endif\n");
+}
+
+void
+reportDiagnostics()
+{
+       List l;
+
+       for (l = operators; l; l = l->next) {
+               Operator op = (Operator) l->x;
+               if (!op->ref) {
+                       fprintf(stderr, "warning: Unreferenced Operator: %s\n", op->name);
+               }
+       }
+       for (l = rules; l; l = l->next) {
+               Rule r = (Rule) l->x;
+               if (!r->used && r->num < max_ruleAST) {
+                       fprintf(stderr, "warning: Unused Rule: #%d\n", r->erulenum);
+               }
+       }
+       if (!start->pmap) {
+               fprintf(stderr, "warning: Start Nonterminal (%s) does not appear on LHS.\n", start->name);
+       }
+
+       fprintf(stderr, "start symbol = \"%s\"\n", start->name);
+       fprintf(stderr, "# of states = %d\n", globalMap->count-1);
+       fprintf(stderr, "# of nonterminals = %d\n", max_nonterminal-1);
+       fprintf(stderr, "# of user nonterminals = %d\n", last_user_nonterminal-1);
+       fprintf(stderr, "# of rules = %d\n", max_rule);
+       fprintf(stderr, "# of user rules = %d\n", max_ruleAST);
+}
diff --git a/support/tools/Burg/burg.shar.gz b/support/tools/Burg/burg.shar.gz
new file mode 100644 (file)
index 0000000..173bbfd
Binary files /dev/null and b/support/tools/Burg/burg.shar.gz differ
diff --git a/support/tools/Burg/burs.c b/support/tools/Burg/burs.c
new file mode 100644 (file)
index 0000000..b4f8b83
--- /dev/null
@@ -0,0 +1,71 @@
+char rcsid_burs[] = "$Id$";
+
+#include "b.h"
+
+Item_Set errorState;
+
+static void doLeaf ARGS((Operator));
+
+static void
+doLeaf(leaf) Operator leaf;
+{
+       int new;
+       List pl;
+       Item_Set ts;
+       Item_Set tmp;
+
+       assert(leaf->arity == 0);
+
+       ts = newItem_Set(leaf->table->relevant);
+
+       for (pl = rules; pl; pl = pl->next) {
+               Rule p = (Rule) pl->x;
+               if (p->pat->op == leaf) {       
+                       if (!ts->virgin[p->lhs->num].rule || p->delta < ts->virgin[p->lhs->num].delta) {
+                               ts->virgin[p->lhs->num].rule = p;
+                               ASSIGNCOST(ts->virgin[p->lhs->num].delta, p->delta);
+                               ts->op = leaf;
+                       }
+               }
+       }
+       trim(ts);
+       zero(ts);
+       tmp = encode(globalMap, ts, &new);
+       if (new) {
+               closure(ts);
+               leaf->table->transition[0] = ts;
+               addQ(globalQ, ts);
+       } else {
+               leaf->table->transition[0] = tmp;
+               freeItem_Set(ts);
+       }
+}
+
+void
+build()
+{
+       int new;
+       List ol;
+       Item_Set ts;
+
+       globalQ = newQ();
+       globalMap = newMapping(GLOBAL_MAP_SIZE);
+
+       ts = newItem_Set(0);
+       errorState = encode(globalMap, ts, &new);
+       ts->closed = ts->virgin;
+       addQ(globalQ, ts);
+
+       foreachList((ListFn) doLeaf, leaves);
+
+       debug(debugTables, printf("---initial set of states ---\n"));
+       debug(debugTables, dumpMapping(globalMap));
+       debug(debugTables, foreachList((ListFn) dumpItem_Set, globalQ->head));
+       
+       for (ts = popQ(globalQ); ts; ts = popQ(globalQ)) {
+               for (ol = operators; ol; ol = ol->next) {
+                       Operator op = (Operator) ol->x;
+                       addToTable(op->table, ts);
+               }
+       }
+}
diff --git a/support/tools/Burg/closure.c b/support/tools/Burg/closure.c
new file mode 100644 (file)
index 0000000..70e1626
--- /dev/null
@@ -0,0 +1,95 @@
+char rcsid_closure[] = "$Id$";
+
+#include <stdio.h>
+#include "b.h"
+
+int prevent_divergence = 0;
+
+List chainrules;
+
+void
+findChainRules()
+{
+       List pl;
+
+       assert(!chainrules);
+
+       for (pl = rules; pl; pl = pl->next) {
+               Rule p = (Rule) pl->x;
+               if (!p->pat->op) {
+                       chainrules = newList(p, chainrules);
+               } else {
+                       p->pat->op->table->rules = newList(p, p->pat->op->table->rules);
+                       addRelevant(p->pat->op->table->relevant, p->lhs->num);
+               }
+       }
+}
+
+void
+zero(t) Item_Set t;
+{
+       int i;
+       DeltaCost base;
+       int exists;
+       int base_nt;
+
+       assert(!t->closed);
+
+       ZEROCOST(base);
+       exists = 0;
+       for (i = 0; i < max_nonterminal; i++) {
+               if (t->virgin[i].rule) {
+                       if (exists) {
+                               if (LESSCOST(t->virgin[i].delta, base)) {
+                                       ASSIGNCOST(base, t->virgin[i].delta);
+                                       base_nt = i;
+                               }
+                       } else {
+                               ASSIGNCOST(base, t->virgin[i].delta);
+                               exists = 1;
+                               base_nt = i;
+                       }
+               }
+       }
+       if (!exists) {
+               return;
+       }
+       for (i = 0; i < max_nonterminal; i++) {
+               if (t->virgin[i].rule) {
+                       MINUSCOST(t->virgin[i].delta, base);
+               }
+               NODIVERGE(t->virgin[i].delta, t, i, base_nt);
+       }
+}
+
+void
+closure(t) Item_Set t;
+{
+       int changes;
+       List pl;
+
+       assert(!t->closed);
+       t->closed = itemArrayCopy(t->virgin);
+
+       changes = 1;
+       while (changes) {
+               changes = 0;
+               for (pl = chainrules; pl; pl = pl->next) {
+                       Rule p = (Rule) pl->x;
+                       register Item *rhs_item = &t->closed[p->pat->children[0]->num];
+
+                       if (rhs_item->rule) {   /* rhs is active */
+                               DeltaCost dc;
+                               register Item *lhs_item = &t->closed[p->lhs->num];
+
+                               ASSIGNCOST(dc, rhs_item->delta);
+                               ADDCOST(dc, p->delta);
+                               if (LESSCOST(dc, lhs_item->delta) || !lhs_item->rule) {
+                                       ASSIGNCOST(lhs_item->delta, dc);
+                                       lhs_item->rule = p;
+                                       changes = 1;
+                               }
+                       }
+               }
+       }
+}
diff --git a/support/tools/Burg/delta.c b/support/tools/Burg/delta.c
new file mode 100644 (file)
index 0000000..d796549
--- /dev/null
@@ -0,0 +1,143 @@
+char rcsid_delta[] = "$Id$";
+
+#include <stdio.h>
+#include "b.h"
+#include "fe.h"
+
+int principleCost = 0;
+int lexical = 0;
+
+#ifndef NOLEX
+void
+ASSIGNCOST(l, r) DeltaPtr l; DeltaPtr r;
+{
+       int i;
+
+       if (lexical) {
+               for (i = 0; i < DELTAWIDTH; i++) {
+                       l[i] = r[i];
+               }
+       } else {
+                       l[0] = r[0];
+       }
+}
+
+void
+ADDCOST(l, r) DeltaPtr l; DeltaPtr r;
+{
+       int i;
+
+       if (lexical) {
+               for (i = 0; i < DELTAWIDTH; i++) {
+                       l[i] += r[i];
+               }
+       } else {
+               l[0] += r[0];
+       }
+}
+
+void
+MINUSCOST(l, r) DeltaPtr l; DeltaPtr r;
+{
+       int i;
+
+       if (lexical) {
+               for (i = 0; i < DELTAWIDTH; i++) {
+                       l[i] -= r[i];
+               }
+       } else {
+               l[0] -= r[0];
+       }
+}
+
+void
+ZEROCOST(x) DeltaPtr x;
+{
+       int i;
+
+       if (lexical) {
+               for (i = 0; i < DELTAWIDTH; i++) {
+                       x[i] = 0;
+               }
+       } else {
+               x[0] = 0;
+       }
+}
+
+int
+LESSCOST(l, r) DeltaPtr l; DeltaPtr r;
+{
+       int i;
+
+       if (lexical) {
+               for (i = 0; i < DELTAWIDTH; i++) {
+                       if (l[i] < r[i]) {
+                               return 1;
+                       } else if (l[i] > r[i]) {
+                               return 0;
+                       }
+               }
+               return 0;
+       } else {
+               return l[0] < r[0];
+       }
+}
+
+int
+EQUALCOST(l, r) DeltaPtr l; DeltaPtr r;
+{
+       int i;
+
+       if (lexical) {
+               for (i = 0; i < DELTAWIDTH; i++) {
+                       if (l[i] != r[i]) {
+                               return 0;
+                       }
+               }
+               return 1;
+       } else {
+               return l[0] == r[0];
+       }
+}
+#endif /* NOLEX */
+
+void
+CHECKDIVERGE(c, its, nt, base) DeltaPtr c; Item_Set its; int nt; int base;
+{
+       int i;
+
+       if (prevent_divergence <= 0) {
+               return;
+       }
+       if (lexical) {
+#ifndef NOLEX
+               for (i = 0; i < DELTAWIDTH; i++) {
+                       if (c[i] > prevent_divergence) {
+                               char ntname[100];
+                               char basename[100];
+                               nonTerminalName(ntname, nt);
+                               nonTerminalName(basename, base);
+                               fprintf(stderr, "ERROR:  The grammar appears to diverge\n");
+                               fprintf(stderr, "\tRelative Costs: %s(0), %s(%d)\n", basename, ntname, c[i]);
+                               fprintf(stderr, "\tOffending Operator: %s\n", its->op->name);
+                               fprintf(stderr, "\tOffending Tree: ");
+                               printRepresentative(stderr, its);
+                               fprintf(stderr, "\n");
+                               exit(1);
+                       }
+               }
+#endif /*NOLEX*/
+       } else if (PRINCIPLECOST(c) > prevent_divergence) {
+               char ntname[100];
+               char basename[100];
+               nonTerminalName(ntname, nt);
+               nonTerminalName(basename, base);
+               fprintf(stderr, "ERROR:  The grammar appears to diverge\n");
+               fprintf(stderr, "\tRelative Costs: %s(0), %s(%d)\n", basename, ntname, PRINCIPLECOST(c));
+               fprintf(stderr, "\tOffending Operator: %s\n", its->op->name);
+               fprintf(stderr, "\tOffending Tree: ");
+               printRepresentative(stderr, its);
+               fprintf(stderr, "\n");
+               exit(1);
+       }
+}
diff --git a/support/tools/Burg/fe.c b/support/tools/Burg/fe.c
new file mode 100644 (file)
index 0000000..36b373d
--- /dev/null
@@ -0,0 +1,403 @@
+char rcsid_fe[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+#include "fe.h"
+
+int grammarflag;
+
+static int arity;
+
+List   ruleASTs;
+List   grammarNts;
+
+static void doBinding ARGS((Binding));
+static void doDecl ARGS((Arity));
+static NonTerminal lookup ARGS((Pattern));
+static NonTerminal normalize ARGS((PatternAST, NonTerminal, Pattern *));
+static void doEnterNonTerm ARGS((RuleAST));
+static void doRule ARGS((RuleAST));
+static void doTable ARGS((Operator));
+
+static void
+doBinding(b) Binding b;
+{
+       int new;
+       Symbol s;
+
+       s = enter(b->name, &new);
+       if (!new) {
+               fprintf(stderr, "Non-unique name: %s\n", b->name);
+               exit(1);
+       }
+       s->tag = OPERATOR;
+       s->u.op = newOperator(b->name, b->opnum, arity);
+       if (arity == 0) {
+               leaves = newList(s->u.op, leaves);
+       }
+}
+
+static void
+doDecl(a) Arity a;
+{
+       if (!a) {
+               return;
+       }
+       arity = a->arity;
+       foreachList((ListFn) doBinding, a->bindings);
+}
+
+
+static List xpatterns;
+static int tcount;
+
+static NonTerminal
+lookup(p) Pattern p;
+{
+       char buf[10];
+       char *s;
+       List l;
+       NonTerminal n;
+       DeltaCost dummy;
+
+       for (l = xpatterns; l; l = l->next) {
+               Pattern x = (Pattern) l->x;
+               if (x->op == p->op 
+                               && x->children[0] == p->children[0]
+                               && x->children[1] == p->children[1]) {
+                       return x->normalizer;
+               }
+       }
+       sprintf(buf, "n%%%d", tcount++);
+       s = (char *) zalloc(strlen(buf)+1);
+       strcpy(s, buf);
+       n = newNonTerminal(s);
+       p->normalizer = n;
+       xpatterns = newList(p, xpatterns);
+       ZEROCOST(dummy);
+       (void) newRule(dummy, 0, n, p);
+       return n;
+}
+
+static NonTerminal
+normalize(ast, nt, patt) PatternAST ast; NonTerminal nt; Pattern *patt;
+{
+       Symbol s;
+       int new;
+       Pattern dummy;
+
+       s = enter(ast->op, &new);
+       ast->sym = s;
+       if (new) { 
+               fprintf(stderr, "Illegal use of %s --- undefined symbol\n", s->name);
+               exit(1);
+               return 0; /* shut up compilers */
+       } else if (s->tag == NONTERMINAL) {
+               if (ast->children) {
+                       fprintf(stderr, "Illegal use of %s, a non-terminal, as a terminal\n", s->name);
+                       exit(1);
+               }
+               *patt = newPattern(0);
+               (*patt)->children[0] = s->u.nt;
+               return s->u.nt;
+       } else {
+               s->u.op->ref = 1;
+               *patt = newPattern(s->u.op);
+               if (s->u.op->arity == -1) {
+                       if (!ast->children) {
+                               s->u.op->arity = 0;
+                               leaves = newList(s->u.op, leaves);
+                       } else if (!ast->children->next) {
+                               s->u.op->arity = 1;
+                       } else if (!ast->children->next->next) {
+                               s->u.op->arity = 2;
+                       } else {
+                               fprintf(stderr, "ERROR: Too many children (max = 2) for \"%s\"\n", s->name);
+                               exit(1);
+                       }
+                       if (s->u.op->arity > max_arity) {
+                               max_arity = s->u.op->arity;
+                       }
+               }
+               switch (s->u.op->arity) {
+               default:
+                       assert(0);
+                       break;
+               case 0:
+                       if (ast->children) {
+                               fprintf(stderr, "ERROR: Incorrect number of children for leaf operator, \"%s\"\n", s->name);
+                               exit(1);
+                       }
+                       break;
+               case 1:
+                       if (!ast->children || ast->children->next) {
+                               fprintf(stderr, "ERROR: Incorrect number of children for unary operator, \"%s\"\n", s->name);
+                               exit(1);
+                       }
+                       (*patt)->children[0] = normalize((PatternAST) ast->children->x, 0, &dummy);
+                       break;
+               case 2:
+                       if (!ast->children || !ast->children->next) {
+                               fprintf(stderr, "ERROR: Incorrect number of children for binary operator, \"%s\"\n", s->name);
+                               exit(1);
+                       }
+                       (*patt)->children[0] = normalize((PatternAST) ast->children->x, 0, &dummy);
+                       (*patt)->children[1] = normalize((PatternAST) ast->children->next->x, 0, &dummy);
+                       break;
+               }
+               if (nt) {
+                       (*patt)->normalizer = nt;
+                       return nt;
+               } else {
+                       return lookup(*patt);
+               }
+       }
+}
+
+static void
+doEnterNonTerm(ast) RuleAST ast;
+{
+       int new;
+       Symbol s;
+       DeltaCost delta;
+       int i;
+       IntList p;
+
+
+       s = enter(ast->lhs, &new);
+       if (new) {
+               s->u.nt = newNonTerminal(s->name);
+               s->tag = NONTERMINAL;
+       } else {
+               if (s->tag != NONTERMINAL) {
+                       fprintf(stderr, "Illegal use of %s as a non-terminal\n", s->name);
+                       exit(1);
+               }
+       }
+       ZEROCOST(delta);
+       for (p = ast->cost, i = 0; p; p = p->next, i++) {
+               int x = p->x;
+#ifndef NOLEX
+               if (lexical) {
+                       if (i < DELTAWIDTH) {
+                               delta[i] = x;
+                       }
+               } else 
+#endif /* NOLEX */
+               {
+                       if (i == principleCost) {
+                               PRINCIPLECOST(delta) = x;
+                       }
+               }
+       }
+       ast->rule = newRule(delta, ast->erulenum, s->u.nt, 0);
+}
+
+static void
+doRule(ast) RuleAST ast;
+{
+       Pattern pat;
+
+       (void) normalize(ast->pat, ast->rule->lhs, &pat);
+       ast->rule->pat = pat;
+}
+
+static void
+doTable(op) Operator op;
+{
+       op->table = newTable(op);
+}
+
+void 
+doSpec(decls, rules) List decls; List rules;
+{
+       foreachList((ListFn) doDecl, decls);
+       debug(debugTables, foreachList((ListFn) dumpOperator_l, operators));
+
+       ruleASTs = rules;
+       reveachList((ListFn) doEnterNonTerm, rules);
+
+       last_user_nonterminal = max_nonterminal;
+
+       reveachList((ListFn) doRule, rules);
+       debug(debugTables, foreachList((ListFn) dumpRule, rules));
+
+       foreachList((ListFn) doTable, operators);
+}
+
+void
+doStart(name) char *name;
+{
+       Symbol s;
+       int new;
+
+       if (start) {
+               yyerror1("Redeclaration of start symbol to be ");
+               fprintf(stderr, "\"%s\"\n", name);
+               exit(1);
+       }
+       s = enter(name, &new);
+       if (new) {
+               s->u.nt = newNonTerminal(s->name);
+               s->tag = NONTERMINAL;
+       } else {
+               if (s->tag != NONTERMINAL) {
+                       fprintf(stderr, "Illegal use of %s as a non-terminal\n", s->name);
+                       exit(1);
+               }
+       }
+}
+
+void
+doGrammarNts()
+{
+       List l;
+       int new;
+
+       for (l = grammarNts; l; l = l->next) {
+               char *n = (char*) l->x;
+               Symbol s;
+
+               s = enter(n, &new);
+               if (new) {
+                       fprintf(stderr, "ERROR: %%gram, unused non-terminal: \"%s\"\n", n);
+                       exit(1);
+               }
+               if (s->tag != NONTERMINAL) {
+                       fprintf(stderr, "ERROR: %%gram, Not a non-terminal: \"%s\"\n", n);
+                       exit(1);
+               }
+               l->x = s;
+       }
+}
+
+void
+doGram(nts) List nts;
+{
+       if (grammarNts) {
+               yyerror1("Redeclaration of %%gram\n");
+               exit(1);
+       }
+       grammarNts = nts;
+}
+
+Arity 
+newArity(ar, b) int ar; List b;
+{
+       Arity a = (Arity) zalloc(sizeof(struct arity));
+       a->arity = ar;
+       a->bindings = b;
+       return a;
+}
+
+Binding 
+newBinding(name, opnum) char *name; int opnum;
+{
+       Binding b = (Binding) zalloc(sizeof(struct binding));
+       if (opnum == 0) {
+               yyerror1("ERROR: Non-positive external symbol number, ");
+               fprintf(stderr, "%d", opnum);
+               exit(1);
+       }
+       b->name = name;
+       b->opnum = opnum;
+       return b;
+}
+
+PatternAST
+newPatternAST(op, children) char *op; List children;
+{
+       PatternAST p = (PatternAST) zalloc(sizeof(struct patternAST));
+       p->op = op;
+       p->children = children;
+       return p;
+}
+
+int max_ruleAST;
+
+RuleAST
+newRuleAST(lhs, pat, erulenum, cost) char *lhs; PatternAST pat; int erulenum; IntList cost;
+{
+       RuleAST p = (RuleAST) zalloc(sizeof(struct ruleAST));
+       p->lhs = lhs;
+       p->pat = pat;
+       if (erulenum <= 0) {
+               yyerror1("External Rulenumber ");
+               fprintf(stderr, "(%d) <= 0\n", erulenum);
+               exit(1);
+       }
+       p->erulenum = erulenum;
+       p->cost = cost;
+       max_ruleAST++;
+       return p;
+}
+
+void
+dumpBinding(b) Binding b;
+{
+       printf("%s=%d ", b->name, b->opnum);
+}
+
+void
+dumpArity(a) Arity a;
+{
+       List l;
+
+       printf("Arity(%d) ", a->arity);
+       for (l = a->bindings; l; l = l->next) {
+               Binding b = (Binding) l->x;
+               dumpBinding(b);
+       }
+       printf("\n");
+}
+
+void
+dumpPatternAST(p) PatternAST p;
+{
+       List l;
+
+       printf("%s", p->op);
+       if (p->children) {
+               printf("(");
+               for (l = p->children; l; l = l->next) {
+                       PatternAST past = (PatternAST) l->x;
+                       dumpPatternAST(past);
+                       if (l->next) {
+                               printf(", ");
+                       }
+               }
+               printf(")");
+       }
+}
+
+void
+dumpRuleAST(p) RuleAST p;
+{
+       printf("%s : ", p->lhs);
+       dumpPatternAST(p->pat);
+       printf(" = %d (%ld)\n", p->erulenum, (long) p->cost);
+}
+
+void
+dumpDecls(decls) List decls;
+{
+       List l;
+
+       for (l = decls; l; l = l->next) {
+               Arity a = (Arity) l->x;
+               dumpArity(a);
+       }
+}
+
+void
+dumpRules(rules) List rules;
+{
+       List l;
+
+       for (l = rules; l; l = l->next) {
+               RuleAST p = (RuleAST) l->x;
+               dumpRuleAST(p);
+       }
+}
+
diff --git a/support/tools/Burg/fe.h b/support/tools/Burg/fe.h
new file mode 100644 (file)
index 0000000..5cef79b
--- /dev/null
@@ -0,0 +1,127 @@
+/* $Id$ */
+
+struct binding {
+       char    *name;
+       int     opnum;
+};
+typedef struct binding *Binding;
+
+struct arity {
+       int     arity;
+       List    bindings;
+};
+typedef struct arity   *Arity;
+
+struct patternAST {
+       struct symbol *sym;
+       char    *op;
+       List    children;
+};
+typedef struct patternAST      *PatternAST;
+
+struct ruleAST {
+       char                    *lhs;
+       PatternAST              pat;
+       int                     erulenum;
+       IntList                 cost;
+       struct rule             *rule;
+       struct strTableElement  *kids;
+       struct strTableElement  *nts;
+};
+typedef struct ruleAST *RuleAST;
+
+typedef enum {
+       UNKNOWN,
+       OPERATOR,
+       NONTERMINAL
+} TagType;
+
+struct symbol {
+       char    *name;
+       TagType tag;
+       union {
+               NonTerminal     nt;
+               Operator        op;
+       } u;
+};
+typedef struct symbol  *Symbol;
+
+struct strTableElement {
+       char *str;
+       IntList erulenos;
+       char *ename;
+};
+typedef struct strTableElement *StrTableElement;
+
+struct strTable {
+       List elems;
+};
+typedef struct strTable        *StrTable;
+
+extern StrTable newStrTable ARGS((void));
+extern StrTableElement addString ARGS((StrTable, char *, int, int *));
+
+extern void doSpec ARGS((List, List));
+extern Arity newArity ARGS((int, List));
+extern Binding newBinding ARGS((char *, int));
+extern PatternAST newPatternAST ARGS((char *, List));
+extern RuleAST newRuleAST ARGS((char *, PatternAST, int, IntList));
+extern Symbol enter ARGS((char *, int *));
+extern Symbol newSymbol ARGS((char *));
+
+extern void makeDebug ARGS((void));
+extern void makeSimple ARGS((void));
+extern void makePlanks ARGS((void));
+extern void makeOpLabel ARGS((void));
+extern void makeChild ARGS((void));
+extern void makeOperators ARGS((void));
+extern void makeLabel ARGS((void));
+extern void makeString ARGS((void));
+extern void makeString ARGS((void));
+extern void makeReduce ARGS((void));
+extern void makeRuleTable ARGS((void));
+extern void makeTables ARGS((void));
+extern void makeTreecost ARGS((void));
+extern void makePrint ARGS((void));
+extern void makeRule ARGS((void));
+extern void makeNts ARGS((void));
+extern void makeKids ARGS((void));
+extern void startBurm ARGS((void));
+extern void startOptional ARGS((void));
+extern void makePlankLabel ARGS((void));
+extern void makeStateLabel ARGS((void));
+extern void makeStringArray ARGS((void));
+extern void makeNonterminalArray ARGS((void));
+extern void makeCostArray ARGS((void));
+extern void makeLHSmap ARGS((void));
+extern void makeClosureArray ARGS((void));
+extern void makeOperatorVector ARGS((void));
+extern void endOptional ARGS((void));
+extern void reportDiagnostics ARGS((void));
+extern void makeNonterminals ARGS((void));
+extern int opsOfArity ARGS((int));
+
+extern void yypurge ARGS((void));
+extern void yyfinished ARGS((void));
+
+extern void printRepresentative ARGS((FILE *, Item_Set));
+
+extern void dumpRules ARGS((List));
+extern void dumpDecls ARGS((List));
+extern void dumpRuleAST ARGS((RuleAST));
+extern void dumpPatternAST ARGS((PatternAST));
+extern void dumpArity ARGS((Arity));
+extern void dumpBinding ARGS((Binding));
+extern void dumpStrTable ARGS((StrTable));
+
+extern int yylex ARGS((void));
+extern int yyparse ARGS((void));
+
+extern int     max_ruleAST;
+extern List    ruleASTs;
+
+extern FILE    *outfile;
+extern char    *prefix;
+extern int     trimflag;
+extern int     speedflag;
+extern int     grammarflag;
diff --git a/support/tools/Burg/gram.y b/support/tools/Burg/gram.y
new file mode 100644 (file)
index 0000000..f6f16fa
--- /dev/null
@@ -0,0 +1,90 @@
+%{
+char rcsid_gram[] = "$Id$";
+
+#include <stdio.h>
+#include "b.h"
+#include "fe.h"
+%}
+
+%union {
+       int y_int;
+       char *y_string;
+       Arity y_arity;
+       Binding y_binding;
+       PatternAST y_patternAST;
+       RuleAST y_ruleAST;
+       List y_list;
+       IntList y_intlist;
+}
+
+%start full
+
+%term ERROR
+%term K_TERM
+%term K_GRAM
+%term K_START
+%term K_PPERCENT
+%term INT
+%term ID
+
+%token <y_string> ID
+%token <y_int> INT
+
+%type <y_arity> decl
+%type <y_binding> binding
+%type <y_intlist> cost costtail
+%type <y_ruleAST> rule
+%type <y_patternAST> pattern
+%type <y_list> decls rules bindinglist grammarlist
+%%
+
+
+full   : spec
+       | spec K_PPERCENT
+               { yyfinished(); }
+       ;
+
+spec   : decls K_PPERCENT rules
+               = { doSpec($1, $3); }
+       ;
+
+decls  : /* lambda */  = { $$ = 0; }
+       | decls decl    = { $$ = newList($2, $1); }
+       ;
+
+decl   : K_TERM bindinglist    = { $$ = newArity(-1, $2); }
+       | K_GRAM grammarlist    = { $$ = 0; doGram($2); }
+       | K_START ID            = { $$ = 0; doStart($2); }      /* kludge */
+       ;
+
+grammarlist    : /* lambda */          = { $$ = 0; }
+               | grammarlist ID        = { $$ = newList($2, $1); }
+               ;
+
+bindinglist    : /* lambda */          = { $$ = 0; }
+               | bindinglist binding   = { $$ = newList($2, $1); }
+               ;
+
+binding        : ID '=' INT    = { $$ = newBinding($1, $3); }
+       ;
+
+rules  : /* lambda */  = { $$ = 0; }
+       | rules rule    = { $$ = newList($2, $1); }
+       ;
+
+rule   : ID ':' pattern '=' INT cost ';'       = { $$ = newRuleAST($1, $3, $5, $6); }
+               ;
+
+pattern        : ID                                    = { $$ = newPatternAST($1, 0); }
+       | ID '(' pattern ')'                    = { $$ = newPatternAST($1, newList($3,0)); }
+       | ID '(' pattern ',' pattern ')'        = { $$ = newPatternAST($1, newList($3, newList($5, 0))); }
+       ;
+
+cost   : /* lambda */          = { $$ = 0; }
+       | '(' INT costtail ')'  = { $$ = newIntList($2, $3); }
+       ;
+
+costtail       : /* lambda */          = { $$ = 0; }
+               | ',' INT costtail      = { $$ = newIntList($2, $3); }
+               | INT costtail          = { $$ = newIntList($1, $2); }
+               ;
diff --git a/support/tools/Burg/item.c b/support/tools/Burg/item.c
new file mode 100644 (file)
index 0000000..4a9f4a3
--- /dev/null
@@ -0,0 +1,133 @@
+char rcsid_item[] = "$Id$";
+
+#include "b.h"
+#include <stdio.h>
+#include <string.h>
+#include "fe.h"
+
+static Item_Set fptr;
+
+ItemArray
+newItemArray()
+{
+       ItemArray ia;
+       ia = (ItemArray) zalloc(max_nonterminal *sizeof(*ia));
+       return ia;
+}
+
+ItemArray
+itemArrayCopy(src) ItemArray src;
+{
+       ItemArray dst;
+
+       dst = newItemArray();
+       memcpy(dst, src, max_nonterminal * sizeof(*dst));
+       return dst;
+}
+
+Item_Set
+newItem_Set(relevant) Relevant relevant;
+{
+       Item_Set ts;
+       
+       if (fptr) {
+               ts = fptr;
+               fptr = 0;
+               memset(ts->virgin, 0, max_nonterminal * sizeof(struct item));
+               if (ts->closed) {
+                       zfree(ts->closed);
+                       ts->closed = 0;
+               }
+               ts->num = 0;
+               ts->op = 0;
+       } else {
+               ts = (Item_Set) zalloc(sizeof(struct item_set));
+               ts->virgin = newItemArray();
+       }
+       ts->relevant = relevant;
+       return ts;
+}
+
+void
+freeItem_Set(ts) Item_Set ts;
+{
+       assert(!fptr);
+       fptr = ts;
+}
+
+int
+equivSet(a, b) Item_Set a; Item_Set b;
+{
+       register Relevant r;
+       register int nt;
+       register Item *aa = a->virgin;
+       register Item *ba = b->virgin;
+
+       /*
+       return !bcmp(a->virgin, b->virgin, max_nonterminal * sizeof(Item));
+       */
+
+       r = a->relevant ? a->relevant : b->relevant;
+       assert(r);
+
+       if (a->op && b->op && a->op != b->op) {
+               return 0;
+       }
+       for (; (nt = *r) != 0; r++) {
+               if (aa[nt].rule != ba[nt].rule || !EQUALCOST(aa[nt].delta, ba[nt].delta)) {
+                       return 0;
+               }
+       }
+       return 1;
+}
+
+void
+printRepresentative(f, s) FILE *f; Item_Set s;
+{
+       if (!s) {
+               return;
+       }
+       fprintf(f, "%s", s->op->name);
+       switch (s->op->arity) {
+       case 1:
+               fprintf(f, "(");
+               printRepresentative(f, s->kids[0]);
+               fprintf(f, ")");
+               break;
+       case 2:
+               fprintf(f, "(");
+               printRepresentative(f, s->kids[0]);
+               fprintf(f, ", ");
+               printRepresentative(f, s->kids[1]);
+               fprintf(f, ")");
+               break;
+       }
+}
+
+void
+dumpItem(t) Item *t;
+{
+       printf("[%s #%d]", t->rule->lhs->name, t->rule->num);
+       dumpCost(t->delta);
+}
+
+void
+dumpItem_Set(ts) Item_Set ts;
+{
+       int i;
+
+       printf("Item_Set #%d: [", ts->num);
+       for (i = 1; i < max_nonterminal; i++) {
+               if (ts->virgin[i].rule) {
+                       printf(" %d", i);
+                       dumpCost(ts->virgin[i].delta);
+               }
+       }
+       printf(" ]\n");
+}
+
+void
+dumpCost(dc) DeltaCost dc;
+{
+       printf("(%ld)", (long) dc);
+}
diff --git a/support/tools/Burg/lex.c b/support/tools/Burg/lex.c
new file mode 100644 (file)
index 0000000..3d6c5af
--- /dev/null
@@ -0,0 +1,260 @@
+char rcsid_lex[] = "$Id$";
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+#include "fe.h"
+#include "y.tab.h"
+
+static char buf[BUFSIZ];
+
+static int yyline = 1;
+
+typedef int (*ReadFn) ARGS((void));
+
+static char *StrCopy ARGS((char *));
+static int code_get ARGS((void));
+static int simple_get ARGS((void));
+static void ReadCharString ARGS((ReadFn, int));
+static void ReadCodeBlock ARGS((void));
+static void ReadOldComment ARGS((ReadFn));
+
+static char *
+StrCopy(s) char *s;
+{
+       char *t = (char *)zalloc(strlen(s) + 1);
+       strcpy(t,s);
+       return t;
+}
+
+static int
+simple_get()
+{
+       int ch;
+       if ((ch = getchar()) == '\n') {
+               yyline++;
+       }
+       return ch;
+}
+
+static int
+code_get()
+{
+       int ch;
+       if ((ch = getchar()) == '\n') {
+               yyline++;
+       }
+       if (ch != EOF) {
+               fputc(ch, outfile);
+       }
+       return ch;
+}
+
+void
+yypurge()
+{
+       while (code_get() != EOF) ;
+}
+
+
+static void
+ReadCharString(rdfn, which) ReadFn rdfn; int which;
+{
+       int ch;
+       int backslash = 0;
+       int firstline = yyline;
+
+       while ((ch = rdfn()) != EOF) {
+               if (ch == which && !backslash) {
+                       return;
+               }
+               if (ch == '\\' && !backslash) {
+                       backslash = 1;
+               } else {
+                       backslash = 0;
+               }
+       }
+       yyerror1("Unexpected EOF in string on line ");
+       fprintf(stderr, "%d\n", firstline);
+       exit(1);
+}
+
+static void
+ReadOldComment(rdfn) ReadFn rdfn;
+{
+       /* will not work for comments delimiter in string */
+
+       int ch;
+       int starred = 0;
+       int firstline = yyline;
+
+       while ((ch = rdfn()) != EOF) {
+               if (ch == '*') {
+                       starred = 1;
+               } else if (ch == '/' && starred) {
+                       return;
+               } else {
+                       starred = 0;
+               }
+       }
+       yyerror1("Unexpected EOF in comment on line ");
+       fprintf(stderr, "%d\n", firstline);
+       exit(1);
+}
+
+static void
+ReadCodeBlock()
+{
+       int ch;
+       int firstline = yyline;
+
+       while ((ch = getchar()) != EOF) {
+               if (ch == '%') {
+                       ch = getchar();
+                       if (ch != '}') {
+                               yyerror("bad %%");
+                       }
+                       return;
+               }
+               fputc(ch, outfile);
+               if (ch == '\n') {
+                       yyline++;
+               }
+               if (ch == '"' || ch == '\'') {
+                       ReadCharString(code_get, ch);
+               } else if (ch == '/') {
+                       ch = getchar();
+                       if (ch == '*') {
+                               fputc(ch, outfile);
+                               ReadOldComment(code_get);
+                               continue;
+                       } else {
+                               ungetc(ch, stdin);
+                       }
+               }
+       }
+       yyerror1("Unclosed block of C code started on line ");
+       fprintf(stderr, "%d\n", firstline);
+       exit(1);
+}
+
+static int done;
+void
+yyfinished()
+{
+       done = 1;
+}
+
+int
+yylex()
+{
+       int ch;
+       char *ptr = buf;
+
+       if (done) return 0;
+       while ((ch = getchar()) != EOF) {
+               switch (ch) {
+               case ' ':
+               case '\f':
+               case '\t':
+                       continue;
+               case '\n':
+                       yyline++;
+                       continue;
+               case '(':
+               case ')':
+               case ',':
+               case ':':
+               case ';':
+               case '=':
+                       return(ch);
+               case '/':
+                       ch = getchar();
+                       if (ch == '*') {
+                               ReadOldComment(simple_get);
+                               continue;
+                       } else {
+                               ungetc(ch, stdin);
+                               yyerror("illegal char /");
+                               continue;
+                       }
+               case '%':
+                       ch = getchar();
+                       switch (ch) {
+                       case '%':
+                               return (K_PPERCENT);
+                       case '{':
+                               ReadCodeBlock();
+                               continue;
+                       case 's':
+                       case 'g':
+                       case 't':
+                               do {
+                                       if (ptr >= &buf[BUFSIZ]) {
+                                               yyerror("ID too long");
+                                               return(ERROR);
+                                       } else {
+                                               *ptr++ = ch;
+                                       }
+                                       ch = getchar();
+                               } while (isalpha(ch) || isdigit(ch) || ch == '_');
+                               ungetc(ch, stdin);
+                               *ptr = '\0';
+                               if (!strcmp(buf, "term")) return K_TERM;
+                               if (!strcmp(buf, "start")) return K_START;
+                               if (!strcmp(buf, "gram")) return K_GRAM;
+                               yyerror("illegal character after %%");
+                               continue;
+                       default:
+                               yyerror("illegal character after %%");
+                               continue;
+                       }
+               default:
+                       if (isalpha(ch) ) {
+                               do {
+                                       if (ptr >= &buf[BUFSIZ]) {
+                                               yyerror("ID too long");
+                                               return(ERROR);
+                                       } else {
+                                               *ptr++ = ch;
+                                       }
+                                       ch = getchar();
+                               } while (isalpha(ch) || isdigit(ch) || ch == '_');
+                               ungetc(ch, stdin);
+                               *ptr = '\0';
+                               yylval.y_string = StrCopy(buf);
+                               return(ID);
+                       } 
+                       if (isdigit(ch)) {
+                               int val=0;
+                               do {
+                                       val *= 10;
+                                       val += (ch - '0');
+                                       ch = getchar();
+                               } while (isdigit(ch));
+                               ungetc(ch, stdin);
+                               yylval.y_int = val;
+                               return(INT);
+                       }
+                       yyerror1("illegal char ");
+                       fprintf(stderr, "(\\%03o)\n", ch);
+                       exit(1);
+               }
+       }
+       return(0);
+}
+
+void
+yyerror1(str) char *str;
+{
+       fprintf(stderr, "line %d: %s", yyline, str);
+}
+
+void
+yyerror(str) char *str;
+{
+       yyerror1(str);
+       fprintf(stderr, "\n");
+       exit(1);
+}
diff --git a/support/tools/Burg/list.c b/support/tools/Burg/list.c
new file mode 100644 (file)
index 0000000..d3eefa2
--- /dev/null
@@ -0,0 +1,75 @@
+char rcsid_list[] = "$Id$";
+
+#include "b.h"
+
+IntList
+newIntList(x, next) int x; IntList next;
+{
+       IntList l;
+
+       l = (IntList) zalloc(sizeof(*l));
+       assert(l);
+       l->x = x;
+       l->next = next;
+
+       return l;
+}
+
+List
+newList(x, next) void *x; List next;
+{
+       List l;
+
+       l = (List) zalloc(sizeof(*l));
+       assert(l);
+       l->x = x;
+       l->next = next;
+
+       return l;
+}
+
+List
+appendList(x, l) void *x; List l;
+{
+       List last;
+       List p;
+
+       last = 0;
+       for (p = l; p; p = p->next) {
+               last = p;
+       }
+       if (last) {
+               last->next = newList(x, 0);
+               return l;
+       } else {
+               return newList(x, 0);
+       }
+}
+
+void
+foreachList(f, l) ListFn f; List l;
+{
+       for (; l; l = l->next) {
+               (*f)(l->x);
+       }
+}
+
+void
+reveachList(f, l) ListFn f; List l;
+{
+       if (l) {
+               reveachList(f, l->next);
+               (*f)(l->x);
+       }
+}
+
+int
+length(l) List l;
+{
+       int c = 0;
+
+       for(; l; l = l->next) {
+               c++;
+       }
+       return c;
+}
diff --git a/support/tools/Burg/main.c b/support/tools/Burg/main.c
new file mode 100644 (file)
index 0000000..5c13698
--- /dev/null
@@ -0,0 +1,182 @@
+char rcsid_main[] = "$Id$";
+
+#include <math.h>
+#include <stdio.h>
+#include "b.h"
+#include "fe.h"
+
+int debugTables = 0;
+static int simpleTables = 0;
+static int internals = 0;
+static int diagnostics = 0;
+
+static char *inFileName;
+static char *outFileName;
+
+static char version[] = "BURG, Version 1.0";
+
+extern void main ARGS((int argc, char **argv));
+
+void
+main(argc, argv) int argc; char **argv;
+{
+       int i;
+       extern int atoi ARGS((char *));
+
+       for (i = 1; argv[i]; i++) {
+               char **needStr = 0;
+               int *needInt = 0;
+
+               if (argv[i][0] == '-') {
+                       switch (argv[i][1]) {
+                       case 'V':
+                               fprintf(stderr, "%s\n", version);
+                               break;
+                       case 'p':
+                               needStr = &prefix;
+                               break;
+                       case 'o':
+                               needStr = &outFileName;
+                               break;
+                       case 'I':
+                               internals = 1;
+                               break;
+                       case 'T':
+                               simpleTables = 1;
+                               break;
+                       case '=':
+#ifdef NOLEX
+                               fprintf(stderr, "'%s' was not compiled to support lexicographic ordering\n", argv[0]);
+#else
+                               lexical = 1;
+#endif /* NOLEX */
+                               break;
+                       case 'O':
+                               needInt = &principleCost;
+                               break;
+                       case 'c':
+                               needInt = &prevent_divergence;
+                               break;
+                       case 'e':
+                               needInt = &exceptionTolerance;
+                               break;
+                       case 'd':
+                               diagnostics = 1;
+                               break;
+                       case 'S':
+                               speedflag = 1;
+                               break;
+                       case 't':
+                               trimflag = 1;
+                               break;
+                       case 'G':
+                               grammarflag = 1;
+                               break;
+                       default:
+                               fprintf(stderr, "Bad option (%s)\n", argv[i]);
+                               exit(1);
+                       }
+               } else {
+                       if (inFileName) {
+                               fprintf(stderr, "Unexpected Filename (%s) after (%s)\n", argv[i], inFileName);
+                               exit(1);
+                       }
+                       inFileName = argv[i];
+               }
+               if (needInt || needStr) {
+                       char *v;
+                       char *opt = argv[i];
+
+                       if (argv[i][2]) {
+                               v = &argv[i][2];
+                       } else {
+                               v = argv[++i];
+                               if (!v) {
+                                       fprintf(stderr, "Expection argument after %s\n", opt);
+                                       exit(1);
+                               }
+                       }
+                       if (needInt) {
+                               *needInt = atoi(v);
+                       } else if (needStr) {
+                               *needStr = v;
+                       }
+               }
+       }
+
+       if (inFileName) {
+               if(freopen(inFileName, "r", stdin)==NULL) {
+                       fprintf(stderr, "Failed opening (%s)", inFileName);
+                       exit(1);
+               }
+       }
+
+       if (outFileName) {
+               if ((outfile = fopen(outFileName, "w")) == NULL) {
+                       fprintf(stderr, "Failed opening (%s)", outFileName);
+                       exit(1);
+               }
+       } else {
+               outfile = stdout;
+       }
+
+
+       yyparse();
+
+       if (!rules) {
+               fprintf(stderr, "ERROR: No rules present\n");
+               exit(1);
+       }
+
+       findChainRules();
+       findAllPairs();
+       doGrammarNts();
+       build();
+
+       debug(debugTables, foreachList((ListFn) dumpOperator_l, operators));
+       debug(debugTables, printf("---final set of states ---\n"));
+       debug(debugTables, dumpMapping(globalMap));
+
+
+       startBurm();
+       makeNts();
+       if (simpleTables) {
+               makeSimple();
+       } else {
+               makePlanks();
+       }
+
+       startOptional();
+       makeLabel();
+       makeKids();
+
+       if (internals) {
+               makeChild();
+               makeOpLabel();
+               makeStateLabel();
+       }
+       endOptional();
+
+       makeOperatorVector();
+       makeNonterminals();
+       if (internals) {
+               makeOperators();
+               makeStringArray();
+               makeRuleDescArray();
+               makeCostArray();
+               makeDeltaCostArray();
+               makeStateStringArray();
+               makeNonterminalArray();
+               /*
+               makeLHSmap();
+               */
+       }
+       makeClosureArray();
+
+       if (diagnostics) {
+               reportDiagnostics();
+       }
+
+       yypurge();
+       exit(0);
+}
diff --git a/support/tools/Burg/map.c b/support/tools/Burg/map.c
new file mode 100644 (file)
index 0000000..6c3c154
--- /dev/null
@@ -0,0 +1,135 @@
+char rcsid_map[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+#include "fe.h"
+
+Mapping globalMap;
+
+static void growMapping ARGS((Mapping));
+static int hash ARGS((Item_Set, int));
+
+Mapping
+newMapping(size) int size;
+{
+       Mapping m;
+
+       m = (Mapping) zalloc(sizeof(struct mapping));
+       assert(m);
+
+       m->count = 0;
+       m->hash = (List*) zalloc(size * sizeof(List));
+       m->hash_size = size;
+       m->max_size = STATES_INCR;
+       m->set = (Item_Set*) zalloc(m->max_size * sizeof(Item_Set));
+       assert(m->set);
+
+       return m;
+}
+
+static void
+growMapping(m) Mapping m;
+{
+       Item_Set *tmp;
+
+       m->max_size += STATES_INCR;
+       tmp = (Item_Set*) zalloc(m->max_size * sizeof(Item_Set));
+       memcpy(tmp, m->set, m->count * sizeof(Item_Set));
+       zfree(m->set);
+       m->set = tmp;
+}
+
+static int
+hash(ts, mod) Item_Set ts; int mod;
+{
+       register Item *p = ts->virgin;
+       register int v;
+       register Relevant r = ts->relevant;
+       register int nt;
+
+       if (!ts->op) {
+               return 0;
+       }
+
+       v = 0;
+       for (; (nt = *r) != 0; r++) {
+               v ^= ((int)p[nt].rule) + (PRINCIPLECOST(p[nt].delta)<<4);
+       }
+       v >>= 4;
+       v &= (mod-1);
+       return v;
+}
+
+Item_Set
+encode(m, ts, new) Mapping m; Item_Set ts; int *new;
+{
+       int h;
+       List l;
+
+       assert(m);
+       assert(ts);
+       assert(m->count <= m->max_size);
+
+       if (grammarNts && errorState && m == globalMap) {
+               List l;
+               int found;
+
+               found = 0;
+               for (l = grammarNts; l; l = l->next) {
+                       Symbol s;
+                       s = (Symbol) l->x;
+
+                       if (ts->virgin[s->u.nt->num].rule) {
+                               found = 1;
+                               break;
+                       }
+               }
+               if (!found) {
+                       *new = 0;
+                       return errorState;
+               }
+       }
+
+       *new = 0;
+       h = hash(ts, m->hash_size);
+       for (l = m->hash[h]; l; l = l->next) {
+               Item_Set s = (Item_Set) l->x;
+               if (ts->op == s->op && equivSet(ts, s)) {
+                       ts->num = s->num;
+                       return s;
+               }
+       }
+       if (m->count >= m->max_size) {
+               growMapping(m);
+       }
+       assert(m->count < m->max_size);
+       m->set[m->count] = ts;
+       ts->num = m->count++;
+       *new = 1;
+       m->hash[h] = newList(ts, m->hash[h]);
+       return ts;
+}
+
+Item_Set
+decode(m, t) Mapping m; ItemSetNum t;
+{
+       assert(m);
+       assert(t);
+       assert(m->count < m->max_size);
+       assert(t < m->count);
+
+       return m->set[t];
+}
+
+void
+dumpMapping(m) Mapping m;
+{
+       int i;
+
+       printf("BEGIN Mapping: Size=%d\n", m->count);
+       for (i = 0; i < m->count; i++) {
+               dumpItem_Set(m->set[i]);
+       }
+       printf("END Mapping\n");
+}
diff --git a/support/tools/Burg/nonterminal.c b/support/tools/Burg/nonterminal.c
new file mode 100644 (file)
index 0000000..af88dd6
--- /dev/null
@@ -0,0 +1,49 @@
+char rcsid_nonterminal[] = "$Id$";
+
+#include "b.h"
+#include <stdio.h>
+
+NonTerminal    start;
+NonTerminalNum max_nonterminal = 1;
+NonTerminalNum last_user_nonterminal;
+List           nonterminals;
+
+NonTerminal
+newNonTerminal(name) char *name;
+{
+       NonTerminal nt;
+
+       nt = (NonTerminal) zalloc(sizeof(struct nonterminal));
+       assert(nt);
+       if (max_nonterminal == 1) {
+               start = nt;
+       }
+       nt->name = name;
+       nt->num = max_nonterminal++;
+       nonterminals = newList(nt, nonterminals);
+
+       return nt;
+}
+
+int
+nonTerminalName(buf, i) char *buf; int i;
+{
+       List l;
+       extern char *strcpy ARGS((char *, char *));
+
+       for (l = nonterminals; l; l = l->next) {
+               NonTerminal nt = (NonTerminal) l->x;
+               if (nt->num == i) {
+                       strcpy(buf, nt->name);
+                       return 1;
+               }
+       }
+       strcpy(buf, "(Unknown NonTerminal)");
+       return 0;
+}
+
+void
+dumpNonTerminal(n) NonTerminal n;
+{
+       printf("%s(%d)", n->name, n->num);
+}
diff --git a/support/tools/Burg/operator.c b/support/tools/Burg/operator.c
new file mode 100644 (file)
index 0000000..a6df9e3
--- /dev/null
@@ -0,0 +1,48 @@
+char rcsid_operator[] = "$Id$";
+
+#include "b.h"
+#include <stdio.h>
+
+int max_arity = -1;
+
+List operators;
+List leaves;
+
+Operator
+newOperator(name, num, arity) char *name; OperatorNum num; ArityNum arity;
+{
+       Operator op;
+
+       assert(arity <= MAX_ARITY);
+       op = (Operator) zalloc(sizeof(struct operator));
+       assert(op);
+       op->name = name;
+       op->num = num;
+       op->arity = arity;
+
+       operators = newList(op, operators);
+
+       return op;
+}
+
+void
+dumpOperator_s(op) Operator op;
+{
+       printf("Op: %s(%d)=%d\n", op->name, op->arity, op->num);
+}
+
+void
+dumpOperator(op, full) Operator op; int full;
+{
+       dumpOperator_s(op);
+       if (full) {
+               dumpTable(op->table, 0);
+       }
+}
+
+void
+dumpOperator_l(op) Operator op;
+{
+       dumpOperator(op, 1);
+}
+
diff --git a/support/tools/Burg/pattern.c b/support/tools/Burg/pattern.c
new file mode 100644 (file)
index 0000000..472aca5
--- /dev/null
@@ -0,0 +1,38 @@
+char rcsid_pattern[] = "$Id$";
+
+#include <stdio.h>
+#include "b.h"
+
+Pattern
+newPattern(op) Operator op;
+{
+       Pattern p;
+
+       p = (Pattern) zalloc(sizeof(struct pattern));
+       p->op = op;
+       return p;
+}
+
+void
+dumpPattern(p) Pattern p;
+{
+       int i;
+
+       if (!p) {
+               printf("[no-pattern]");
+               return;
+       }
+
+       if (p->op) {
+               printf("%s", p->op->name);
+               if (p->op->arity > 0) {
+                       printf("(");
+                       for (i = 0; i < p->op->arity; i++) {
+                               printf("%s ", p->children[i]->name);
+                       }
+                       printf(")");
+               }
+       } else {
+               printf("%s", p->children[0]->name);
+       }
+}
diff --git a/support/tools/Burg/plank.c b/support/tools/Burg/plank.c
new file mode 100644 (file)
index 0000000..053304e
--- /dev/null
@@ -0,0 +1,920 @@
+char rcsid_plank[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+#include "fe.h"
+
+#define ERROR_VAL 0
+
+int speedflag = 0;
+
+Item_Set *sortedStates;
+static struct stateMapTable smt;
+int exceptionTolerance = 0;
+static int plankSize = 32;
+
+static Plank newPlank ARGS((void));
+static PlankMap newPlankMap ARGS((int));
+static StateMap newStateMap ARGS((void));
+static Exception newException ARGS((int, int));
+static void enterStateMap ARGS((PlankMap, short *, int, int *));
+static List assemblePlanks ARGS((void));
+static void assignRules ARGS((RuleAST));
+static int stateCompare ARGS((Item_Set *, Item_Set *));
+static int ruleCompare ARGS((RuleAST *, RuleAST *));
+static void renumber ARGS((void));
+static short * newVector ARGS((void));
+static int width ARGS((int));
+static PlankMap mapToPmap ARGS((Dimension));
+static void doDimPmaps ARGS((Operator));
+static void doNonTermPmaps ARGS((NonTerminal));
+static void makePmaps ARGS((void));
+static void outPlank ARGS((Plank));
+static void purgePlanks ARGS((List));
+static void inToEx ARGS((void));
+static void makePlankRuleMacros ARGS((void));
+static void makePlankRule ARGS((void));
+static void exceptionSwitch ARGS((List, char *, char *, char *, int, char *));
+static void doPlankLabel ARGS((Operator));
+static void doPlankLabelSafely ARGS((Operator));
+static void doPlankLabelMacrosSafely ARGS((Operator));
+static void makePlankState ARGS((void));
+
+static Plank
+newPlank()
+{
+       Plank p;
+       char buf[50];
+       static int num = 0;
+
+       p = (Plank) zalloc(sizeof(struct plank));
+       sprintf(buf, "%s_plank_%d", prefix, num++);
+       p->name = (char *) zalloc(strlen(buf)+1);
+       strcpy(p->name, buf);
+       return p;
+}
+
+static PlankMap
+newPlankMap(offset) int offset;
+{
+       PlankMap im;
+
+       im = (PlankMap) zalloc(sizeof(struct plankMap));
+       im->offset = offset;
+       return im;
+}
+
+static StateMap
+newStateMap()
+{
+       char buf[50];
+       static int num = 0;
+
+       StateMap sm;
+
+       sm = (StateMap) zalloc(sizeof(struct stateMap));
+       sprintf(buf, "f%d", num++);
+       sm->fieldname = (char *) zalloc(strlen(buf)+1);
+       strcpy(sm->fieldname, buf);
+       return sm;
+}
+
+static Exception
+newException(index, value) int index; int value;
+{
+       Exception e;
+
+       e = (Exception) zalloc(sizeof(struct except));
+       e->index = index;
+       e->value = value;
+       return e;
+}
+
+static void
+enterStateMap(im, v, width, new) PlankMap im; short * v; int width; int *new;
+{
+       int i;
+       StateMap sm;
+       List l;
+       int size;
+
+       assert(im);
+       assert(v);
+       assert(width > 0);
+       size = globalMap->count;
+
+       for (l = smt.maps; l; l = l->next) {
+               int ecount;
+
+               sm = (StateMap) l->x;
+               ecount = 0;
+               for (i = 0; i < size; i++) {
+                       if (v[i] != -1 && sm->value[i] != -1 && v[i] != sm->value[i]) {
+                               if (++ecount > exceptionTolerance) {
+                                       goto again;
+                               }
+                       }
+               }
+               for (i = 0; i < size; i++) {
+                       assert(v[i] >= 0);
+                       assert(sm->value[i] >= 0);
+                       if (v[i] == -1) {
+                               continue;
+                       }
+                       if (sm->value[i] == -1) {
+                               sm->value[i] = v[i];
+                       } else if (v[i] != sm->value[i]) {
+                               im->exceptions = newList(newException(i,v[i]), im->exceptions);
+                       }
+               }
+               im->values = sm;
+               if (width > sm->width) {
+                       sm->width = width;
+               }
+               *new = 0;
+               return;
+       again: ;
+       }
+       sm = newStateMap();
+       im->values = sm;
+       sm->value = v;
+       sm->width = width;
+       *new = 1;
+       smt.maps = newList(sm, smt.maps);
+}
+
+static List
+assemblePlanks()
+{
+       List planks = 0;
+       Plank pl;
+       List p;
+       List s;
+
+       for (s = smt.maps; s; s = s->next) {
+               StateMap sm = (StateMap) s->x;
+               for (p = planks; p; p = p->next) {
+                       pl = (Plank) p->x;
+                       if (sm->width <= plankSize - pl->width) {
+                               pl->width += sm->width;
+                               pl->fields = newList(sm, pl->fields);
+                               sm->plank = pl;
+                               goto next;
+                       }
+               }
+               pl = newPlank();
+               pl->width = sm->width;
+               pl->fields = newList(sm, 0);
+               sm->plank = pl;
+               planks = appendList(pl, planks);
+       next: ;
+       }
+       return planks;
+}
+
+RuleAST *sortedRules;
+
+static int count;
+
+static void
+assignRules(ast) RuleAST ast;
+{
+       sortedRules[count++] = ast;
+}
+
+static int
+stateCompare(s, t) Item_Set *s; Item_Set *t;
+{
+       return strcmp((*s)->op->name, (*t)->op->name);
+}
+
+static int
+ruleCompare(s, t) RuleAST *s; RuleAST *t;
+{
+       return strcmp((*s)->lhs, (*t)->lhs);
+}
+
+void
+dumpSortedStates()
+{
+       int i;
+       
+       printf("dump Sorted States: ");
+       for (i = 0; i < globalMap->count; i++) {
+               printf("%d ", sortedStates[i]->num);
+       }
+       printf("\n");
+}
+
+void
+dumpSortedRules()
+{
+       int i;
+       
+       printf("dump Sorted Rules: ");
+       for (i = 0; i < max_ruleAST; i++) {
+               printf("%d ", sortedRules[i]->rule->erulenum);
+       }
+       printf("\n");
+}
+
+static void
+renumber()
+{
+       int i;
+       Operator previousOp;
+       NonTerminal previousLHS;
+       int base_counter;
+
+       sortedStates = (Item_Set*) zalloc(globalMap->count * sizeof(Item_Set));
+       for (i = 1; i < globalMap->count; i++) {
+               sortedStates[i-1] = globalMap->set[i];
+       }
+       qsort(sortedStates, globalMap->count-1, sizeof(Item_Set), stateCompare);
+       previousOp = 0;
+       for (i = 0; i < globalMap->count-1; i++) {
+               sortedStates[i]->newNum = i;
+               sortedStates[i]->op->stateCount++;
+               if (previousOp != sortedStates[i]->op) {
+                       sortedStates[i]->op->baseNum = i;
+                       previousOp = sortedStates[i]->op;
+               }
+       }
+
+       sortedRules = (RuleAST*) zalloc(max_ruleAST * sizeof(RuleAST));
+       count = 0;
+       foreachList((ListFn) assignRules, ruleASTs);
+       qsort(sortedRules, max_ruleAST, sizeof(RuleAST), ruleCompare);
+       previousLHS = 0;
+       base_counter = 0;
+       for (i = 0; i < max_ruleAST; i++) {
+               if (previousLHS != sortedRules[i]->rule->lhs) {
+                       sortedRules[i]->rule->lhs->baseNum = base_counter;
+                       previousLHS = sortedRules[i]->rule->lhs;
+                       base_counter++; /* make space for 0 */
+               }
+               sortedRules[i]->rule->newNum = base_counter;
+               sortedRules[i]->rule->lhs->ruleCount++;
+               sortedRules[i]->rule->lhs->sampleRule = sortedRules[i]->rule; /* kludge for diagnostics */
+               base_counter++;
+       }
+}
+
+static short *
+newVector()
+{
+       short *p;
+       p = (short *) zalloc(globalMap->count* sizeof(short));
+       return p;
+}
+
+static int
+width(v) int v;
+{
+       int c;
+
+       for (c = 0; v; v >>= 1) {
+               c++;
+       }
+       return c;
+
+}
+
+static PlankMap
+mapToPmap(d) Dimension d;
+{
+       PlankMap im;
+       short *v;
+       int i;
+       int new;
+
+       if (d->map->count == 1) {
+               return 0;
+       }
+       assert(d->map->count > 1);
+       im = newPlankMap(0);
+       v = newVector();
+       for (i = 0; i < globalMap->count-1; i++) {
+               int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num;
+               assert(index >= 0);
+               v[i+1] = index;
+       }
+       v[0] = 0;
+       enterStateMap(im, v, width(d->map->count), &new);
+       if (!new) {
+               zfree(v);
+       }
+       return im;
+}
+
+static void
+doDimPmaps(op) Operator op;
+{
+       int i, j;
+       Dimension d;
+       short *v;
+       PlankMap im;
+       int new;
+
+       if (!op->table->rules) {
+               return;
+       }
+       switch (op->arity) {
+       case 0:
+               break;
+       case 1:
+               d = op->table->dimen[0];
+               if (d->map->count > 1) {
+                       v = newVector();
+                       im = newPlankMap(op->baseNum);
+                       for (i = 0; i < globalMap->count-1; i++) {
+                               int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num;
+                               if (index) {
+                                       Item_Set *ts = transLval(op->table, index, 0);
+                                       v[i+1] = (*ts)->newNum - op->baseNum+1;
+                                       assert(v[i+1] >= 0);
+                               }
+                       }
+                       enterStateMap(im, v, width(d->map->count-1), &new);
+                       if (!new) {
+                               zfree(v);
+                       }
+                       d->pmap = im;
+               }
+               break;
+       case 2:
+               if (op->table->dimen[0]->map->count == 1 && op->table->dimen[1]->map->count == 1) {
+                       op->table->dimen[0]->pmap = 0;
+                       op->table->dimen[1]->pmap = 0;
+               } else if (op->table->dimen[0]->map->count == 1) {
+                       v = newVector();
+                       im = newPlankMap(op->baseNum);
+                       d = op->table->dimen[1];
+                       for (i = 0; i < globalMap->count-1; i++) {
+                               int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num;
+                               if (index) {
+                                       Item_Set *ts = transLval(op->table, 1, index);
+                                       v[i+1] = (*ts)->newNum - op->baseNum+1;
+                                       assert(v[i+1] >= 0);
+                               }
+                       }
+                       enterStateMap(im, v, width(d->map->count-1), &new);
+                       if (!new) {
+                               zfree(v);
+                       }
+                       d->pmap = im;
+               } else if (op->table->dimen[1]->map->count == 1) {
+                       v = newVector();
+                       im = newPlankMap(op->baseNum);
+                       d = op->table->dimen[0];
+                       for (i = 0; i < globalMap->count-1; i++) {
+                               int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num;
+                               if (index) {
+                                       Item_Set *ts = transLval(op->table, index, 1);
+                                       v[i +1] = (*ts)->newNum - op->baseNum +1;
+                                       assert(v[i +1] >= 0);
+                               }
+                       }
+                       enterStateMap(im, v, width(d->map->count-1), &new);
+                       if (!new) {
+                               zfree(v);
+                       }
+                       d->pmap = im;
+               } else {
+                       op->table->dimen[0]->pmap = mapToPmap(op->table->dimen[0]);
+                       op->table->dimen[1]->pmap = mapToPmap(op->table->dimen[1]);
+                       /* output table */
+                       fprintf(outfile, "static unsigned %s %s_%s_transition[%d][%d] = {", 
+                               op->stateCount <= 255 ? "char" : "short",
+                               prefix,
+                               op->name,
+                               op->table->dimen[0]->map->count,
+                               op->table->dimen[1]->map->count);
+                       for (i = 0; i < op->table->dimen[0]->map->count; i++) {
+                               if (i > 0) {
+                                       fprintf(outfile, ",");
+                               }
+                               fprintf(outfile, "\n{");
+                               for (j = 0; j < op->table->dimen[1]->map->count; j++) {
+                                       Item_Set *ts = transLval(op->table, i, j);
+                                       short diff;
+                                       if (j > 0) {
+                                               fprintf(outfile, ",");
+                                               if (j % 10 == 0) {
+                                                       fprintf(outfile, "\t/* row %d, cols %d-%d*/\n",
+                                                               i,
+                                                               j-10,
+                                                               j-1);
+                                               }
+                                       }
+                                       if ((*ts)->num > 0) {
+                                               diff = (*ts)->newNum - op->baseNum +1;
+                                       } else {
+                                               diff = 0;
+                                       }
+                                       fprintf(outfile, "%5d", diff);
+                               }
+                               fprintf(outfile, "}\t/* row %d */", i);
+                       }
+                       fprintf(outfile, "\n};\n");
+               }
+               break;
+       default:
+               assert(0);
+       }
+}
+
+static NonTerminal *ntVector;
+
+static void
+doNonTermPmaps(n) NonTerminal n;
+{
+       short *v;
+       PlankMap im;
+       int new;
+       int i;
+
+       ntVector[n->num] = n;
+       if (n->num >= last_user_nonterminal) {
+               return;
+       }
+       if (n->ruleCount <= 0) {
+               return;
+       }
+       im = newPlankMap(n->baseNum);
+       v = newVector();
+       for (i = 0; i < globalMap->count-1; i++) {
+               Rule r = globalMap->set[sortedStates[i]->num]->closed[n->num].rule;
+               if (r) {
+                       r->used = 1;
+                       v[i+1] = r->newNum - n->baseNum /*safely*/;
+                       assert(v[i+1] >= 0);
+               }
+       }
+       enterStateMap(im, v, width(n->ruleCount+1), &new);
+       if (!new) {
+               zfree(v);
+       }
+       n->pmap = im;
+}
+
+static void
+makePmaps()
+{
+       foreachList((ListFn) doDimPmaps, operators);
+       ntVector = (NonTerminal*) zalloc((max_nonterminal) * sizeof(NonTerminal));
+       foreachList((ListFn) doNonTermPmaps, nonterminals);
+}
+
+static void
+outPlank(p) Plank p;
+{
+       List f;
+       int i;
+
+       fprintf(outfile, "static struct {\n");
+
+       for (f = p->fields; f; f = f->next) {
+               StateMap sm = (StateMap) f->x;
+               fprintf(outfile, "\tunsigned int %s:%d;\n", sm->fieldname, sm->width);
+       }
+
+       fprintf(outfile, "} %s[] = {\n", p->name);
+
+       for (i = 0; i < globalMap->count; i++) {
+               fprintf(outfile, "\t{");
+               for (f = p->fields; f; f = f->next) {
+                       StateMap sm = (StateMap) f->x;
+                       fprintf(outfile, "%4d,", sm->value[i] == -1 ? ERROR_VAL : sm->value[i]);
+               }
+               fprintf(outfile, "},\t/* row %d */\n", i);
+       }
+
+       fprintf(outfile, "};\n");
+}
+
+static void
+purgePlanks(planks) List planks;
+{
+       List p;
+
+       for (p = planks; p; p = p->next) {
+               Plank x = (Plank) p->x;
+               outPlank(x);
+       }
+}
+
+static void
+inToEx()
+{
+       int i;
+       int counter;
+
+       fprintf(outfile, "static short %s_eruleMap[] = {\n", prefix);
+       counter = 0;
+       for (i = 0; i < max_ruleAST; i++) {
+               if (counter > 0) {
+                       fprintf(outfile, ",");
+                       if (counter % 10 == 0) {
+                               fprintf(outfile, "\t/* %d-%d */\n", counter-10, counter-1);
+                       }
+               }
+               if (counter < sortedRules[i]->rule->newNum) {
+                       assert(counter == sortedRules[i]->rule->newNum-1);
+                       fprintf(outfile, "%5d", 0);
+                       counter++;
+                       if (counter > 0) {
+                               fprintf(outfile, ",");
+                               if (counter % 10 == 0) {
+                                       fprintf(outfile, "\t/* %d-%d */\n", counter-10, counter-1);
+                               }
+                       }
+               }
+               fprintf(outfile, "%5d", sortedRules[i]->rule->erulenum);
+               counter++;
+       }
+       fprintf(outfile, "\n};\n");
+}
+
+static void
+makePlankRuleMacros()
+{
+       int i;
+
+       for (i = 1; i < last_user_nonterminal; i++) {
+               List es;
+               PlankMap im = ntVector[i]->pmap;
+               fprintf(outfile, "#define %s_%s_rule(state)\t", prefix, ntVector[i]->name);
+               if (im) {
+                       fprintf(outfile, "%s_eruleMap[", prefix);
+                       for (es = im->exceptions; es; es = es->next) {
+                               Exception e = (Exception) es->x;
+                               fprintf(outfile, "((state) == %d ? %d :", 
+                                               e->index, e->value);
+                       }
+                       fprintf(outfile, "%s[state].%s", 
+                               im->values->plank->name, 
+                               im->values->fieldname);
+                       for (es = im->exceptions; es; es = es->next) {
+                               fprintf(outfile, ")");
+                       }
+                       fprintf(outfile, " +%d]", im->offset);
+
+               } else {
+                       /* nonterminal never appears on LHS. */
+                       assert(ntVector[i] ==  start);
+                       fprintf(outfile, "0");
+               }
+               fprintf(outfile, "\n");
+       }
+       fprintf(outfile, "\n");
+}
+
+static void
+makePlankRule()
+{
+       int i;
+
+       makePlankRuleMacros();
+
+       fprintf(outfile, "#ifdef __STDC__\n");
+       fprintf(outfile, "int %s_rule(int state, int goalnt) {\n", prefix);
+       fprintf(outfile, "#else\n");
+       fprintf(outfile, "int %s_rule(state, goalnt) int state; int goalnt; {\n", prefix);
+       fprintf(outfile, "#endif\n");
+
+       fprintf(outfile, 
+       "\t%s_assert(state >= 0 && state < %d, %s_PANIC(\"Bad state %%d passed to %s_rule\\n\", state));\n",
+                               prefix, globalMap->count, prefix, prefix);
+       fprintf(outfile, "\tswitch(goalnt) {\n");
+
+       for (i = 1; i < last_user_nonterminal; i++) {
+               fprintf(outfile, "\tcase %d:\n", i);
+               fprintf(outfile, "\t\treturn %s_%s_rule(state);\n", prefix, ntVector[i]->name);
+       }
+       fprintf(outfile, "\tdefault:\n");
+       fprintf(outfile, "\t\t%s_PANIC(\"Unknown nonterminal %%d in %s_rule;\\n\", goalnt);\n", prefix, prefix);
+       fprintf(outfile, "\t\tabort();\n");
+       fprintf(outfile, "\t\treturn 0;\n");
+       fprintf(outfile, "\t}\n");
+       fprintf(outfile, "}\n");
+}
+
+static void
+exceptionSwitch(es, sw, pre, post, offset, def) List es; char *sw; char *pre; char *post; int offset; char *def;
+{
+       if (es) {
+               fprintf(outfile, "\t\tswitch (%s) {\n", sw);
+               for (; es; es = es->next) {
+                       Exception e = (Exception) es->x;
+                       fprintf(outfile, "\t\tcase %d: %s %d; %s\n", e->index, pre, e->value+offset, post);
+               }
+               if (def) {
+                       fprintf(outfile, "\t\tdefault: %s;\n", def);
+               }
+               fprintf(outfile, "\t\t}\n");
+       } else {
+               if (def) {
+                       fprintf(outfile, "\t\t%s;\n", def);
+               }
+       }
+}
+
+static void
+doPlankLabel(op) Operator op;
+{
+       PlankMap im0;
+       PlankMap im1;
+       char buf[100];
+
+       fprintf(outfile, "\tcase %d:\n", op->num);
+       switch (op->arity) {
+       case 0:
+               fprintf(outfile, "\t\treturn %d;\n", op->table->transition[0]->newNum);
+               break;
+       case 1:
+               im0 = op->table->dimen[0]->pmap;
+               if (im0) {
+                       exceptionSwitch(im0->exceptions, "l", "return ", "", im0->offset, 0);
+                       fprintf(outfile, "\t\treturn %s[l].%s + %d;\n", 
+                               im0->values->plank->name, im0->values->fieldname, im0->offset);
+               } else {
+                       Item_Set *ts = transLval(op->table, 1, 0);
+                       if (*ts) {
+                               fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum);
+                       } else {
+                               fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL);
+                       }
+               }
+               break;
+       case 2:
+               im0 = op->table->dimen[0]->pmap;
+               im1 = op->table->dimen[1]->pmap;
+               if (!im0 && !im1) {
+                       Item_Set *ts = transLval(op->table, 1, 1);
+                       if (*ts) {
+                               fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum);
+                       } else {
+                               fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL);
+                       }
+               } else if (!im0) {
+                       exceptionSwitch(im1->exceptions, "r", "return ", "", im1->offset, 0);
+                       fprintf(outfile, "\t\treturn %s[r].%s + %d;\n", 
+                               im1->values->plank->name, im1->values->fieldname, im1->offset);
+               } else if (!im1) {
+                       exceptionSwitch(im0->exceptions, "l", "return ", "", im0->offset, 0);
+                       fprintf(outfile, "\t\treturn %s[l].%s + %d;\n", 
+                               im0->values->plank->name, im0->values->fieldname, im0->offset);
+               } else {
+                       assert(im0->offset == 0);
+                       assert(im1->offset == 0);
+                       sprintf(buf, "l = %s[l].%s",
+                               im0->values->plank->name, im0->values->fieldname);
+                       exceptionSwitch(im0->exceptions, "l", "l =", "break;", 0, buf);
+                       sprintf(buf, "r = %s[r].%s",
+                               im1->values->plank->name, im1->values->fieldname);
+                       exceptionSwitch(im1->exceptions, "r", "r =", "break;", 0, buf);
+
+                       fprintf(outfile, "\t\treturn %s_%s_transition[l][r] + %d;\n", 
+                               prefix,
+                               op->name,
+                               op->baseNum);
+               }
+               break;
+       default:
+               assert(0);
+       }
+}
+
+static void
+doPlankLabelMacrosSafely(op) Operator op;
+{
+       PlankMap im0;
+       PlankMap im1;
+
+       switch (op->arity) {
+       case -1:
+               fprintf(outfile, "#define %s_%s_state\t0\n", prefix, op->name);
+               break;
+       case 0:
+               fprintf(outfile, "#define %s_%s_state", prefix, op->name);
+               fprintf(outfile, "\t%d\n", op->table->transition[0]->newNum+1);
+               break;
+       case 1:
+               fprintf(outfile, "#define %s_%s_state(l)", prefix, op->name);
+               im0 = op->table->dimen[0]->pmap;
+               if (im0) {
+                       if (im0->exceptions) {
+                               List es = im0->exceptions;
+                               assert(0);
+                               fprintf(outfile, "\t\tswitch (l) {\n");
+                               for (; es; es = es->next) {
+                                       Exception e = (Exception) es->x;
+                                       fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im0->offset : 0);
+                               }
+                               fprintf(outfile, "\t\t}\n");
+                       }
+                       if (speedflag) {
+                               fprintf(outfile, "\t( %s[l].%s + %d )\n",
+                                       im0->values->plank->name, im0->values->fieldname,
+                                       im0->offset);
+                       } else {
+                               fprintf(outfile, "\t( (%s_TEMP = %s[l].%s) ? %s_TEMP + %d : 0 )\n",
+                                       prefix,
+                                       im0->values->plank->name, im0->values->fieldname,
+                                       prefix,
+                                       im0->offset);
+                       }
+               } else {
+                       Item_Set *ts = transLval(op->table, 1, 0);
+                       if (*ts) {
+                               fprintf(outfile, "\t%d\n", (*ts)->newNum+1);
+                       } else {
+                               fprintf(outfile, "\t%d\n", 0);
+                       }
+               }
+               break;
+       case 2:
+               fprintf(outfile, "#define %s_%s_state(l,r)", prefix, op->name);
+
+               im0 = op->table->dimen[0]->pmap;
+               im1 = op->table->dimen[1]->pmap;
+               if (!im0 && !im1) {
+                       Item_Set *ts = transLval(op->table, 1, 1);
+                       assert(0);
+                       if (*ts) {
+                               fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum+1);
+                       } else {
+                               fprintf(outfile, "\t\treturn %d;\n", 0);
+                       }
+               } else if (!im0) {
+                       assert(0);
+                       if (im1->exceptions) {
+                               List es = im1->exceptions;
+                               fprintf(outfile, "\t\tswitch (r) {\n");
+                               for (; es; es = es->next) {
+                                       Exception e = (Exception) es->x;
+                                       fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im1->offset : 0);
+                               }
+                               fprintf(outfile, "\t\t}\n");
+                       }
+                       fprintf(outfile, "\t\tstate = %s[r].%s; offset = %d;\n", 
+                               im1->values->plank->name, im1->values->fieldname, im1->offset);
+                       fprintf(outfile, "\t\tbreak;\n");
+               } else if (!im1) {
+                       assert(0);
+                       if (im0->exceptions) {
+                               List es = im0->exceptions;
+                               fprintf(outfile, "\t\tswitch (l) {\n");
+                               for (; es; es = es->next) {
+                                       Exception e = (Exception) es->x;
+                                       fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im0->offset : 0);
+                               }
+                               fprintf(outfile, "\t\t}\n");
+                       }
+                       fprintf(outfile, "\t\tstate = %s[l].%s; offset = %d;\n", 
+                               im0->values->plank->name, im0->values->fieldname, im0->offset);
+                       fprintf(outfile, "\t\tbreak;\n");
+               } else {
+                       assert(im0->offset == 0);
+                       assert(im1->offset == 0);
+                       /*
+                       sprintf(buf, "l = %s[l].%s",
+                               im0->values->plank->name, im0->values->fieldname);
+                       exceptionSwitch(im0->exceptions, "l", "l =", "break;", 0, buf);
+                       sprintf(buf, "r = %s[r].%s",
+                               im1->values->plank->name, im1->values->fieldname);
+                       exceptionSwitch(im1->exceptions, "r", "r =", "break;", 0, buf);
+
+                       fprintf(outfile, "\t\tstate = %s_%s_transition[l][r]; offset = %d;\n", 
+                               prefix,
+                               op->name,
+                               op->baseNum);
+                       fprintf(outfile, "\t\tbreak;\n");
+                       */
+
+                       if (speedflag) {
+                               fprintf(outfile, "\t( %s_%s_transition[%s[l].%s][%s[r].%s] + %d)\n",
+                                       prefix,
+                                       op->name,
+                                       im0->values->plank->name, im0->values->fieldname,
+                                       im1->values->plank->name, im1->values->fieldname,
+                                       op->baseNum);
+                       } else {
+                               fprintf(outfile, "\t( (%s_TEMP = %s_%s_transition[%s[l].%s][%s[r].%s]) ? ",
+                                       prefix,
+                                       prefix,
+                                       op->name,
+                                       im0->values->plank->name, im0->values->fieldname,
+                                       im1->values->plank->name, im1->values->fieldname);
+                               fprintf(outfile, "%s_TEMP + %d : 0 )\n",
+                                       prefix,
+                                       op->baseNum);
+                       }
+               }
+               break;
+       default:
+               assert(0);
+       }
+}
+static void
+doPlankLabelSafely(op) Operator op;
+{
+       fprintf(outfile, "\tcase %d:\n", op->num);
+       switch (op->arity) {
+       case -1:
+               fprintf(outfile, "\t\treturn 0;\n");
+               break;
+       case 0:
+               fprintf(outfile, "\t\treturn %s_%s_state;\n", prefix, op->name);
+               break;
+       case 1:
+               fprintf(outfile, "\t\treturn %s_%s_state(l);\n", prefix, op->name);
+               break;
+       case 2:
+               fprintf(outfile, "\t\treturn %s_%s_state(l,r);\n", prefix, op->name);
+               break;
+       default:
+               assert(0);
+       }
+}
+
+static void
+makePlankState()
+{
+       fprintf(outfile, "\n");
+       fprintf(outfile, "int %s_TEMP;\n", prefix);
+       foreachList((ListFn) doPlankLabelMacrosSafely, operators);
+       fprintf(outfile, "\n");
+
+       fprintf(outfile, "#ifdef __STDC__\n");
+       switch (max_arity) {
+       case -1:
+               fprintf(stderr, "ERROR: no terminals in grammar.\n");
+               exit(1);
+       case 0:
+               fprintf(outfile, "int %s_state(int op) {\n", prefix);
+               fprintf(outfile, "#else\n");
+               fprintf(outfile, "int %s_state(op) int op; {\n", prefix);
+               break;
+       case 1:
+               fprintf(outfile, "int %s_state(int op, int l) {\n", prefix);
+               fprintf(outfile, "#else\n");
+               fprintf(outfile, "int %s_state(op, l) int op; int l; {\n", prefix);
+               break;
+       case 2:
+               fprintf(outfile, "int %s_state(int op, int l, int r) {\n", prefix);
+               fprintf(outfile, "#else\n");
+               fprintf(outfile, "int %s_state(op, l, r) int op; int l; int r; {\n", prefix);
+               break;
+       default:
+               assert(0);
+       }
+       fprintf(outfile, "#endif\n");
+
+       fprintf(outfile, "\tregister int %s_TEMP;\n", prefix);
+
+       fprintf(outfile, "#ifndef NDEBUG\n");
+
+       fprintf(outfile, "\tswitch (op) {\n");
+       opsOfArity(2);
+       if (max_arity >= 2) {
+               fprintf(outfile, 
+               "\t\t%s_assert(r >= 0 && r < %d, %s_PANIC(\"Bad state %%d passed to %s_state\\n\", r));\n",
+                               prefix, globalMap->count, prefix, prefix);
+               fprintf(outfile, "\t\t/*FALLTHROUGH*/\n");
+       }
+       opsOfArity(1);
+       if (max_arity > 1) {
+               fprintf(outfile, 
+               "\t\t%s_assert(l >= 0 && l < %d, %s_PANIC(\"Bad state %%d passed to %s_state\\n\", l));\n",
+                               prefix, globalMap->count, prefix, prefix);
+               fprintf(outfile, "\t\t/*FALLTHROUGH*/\n");
+       }
+       opsOfArity(0);
+       fprintf(outfile, "\t\tbreak;\n");
+       fprintf(outfile, "\t}\n");
+       fprintf(outfile, "#endif\n");
+
+       fprintf(outfile, "\tswitch (op) {\n");
+       fprintf(outfile,"\tdefault: %s_PANIC(\"Unknown op %%d in %s_state\\n\", op); abort(); return 0;\n",
+               prefix, prefix);
+       foreachList((ListFn) doPlankLabelSafely, operators);
+       fprintf(outfile, "\t}\n");
+
+       fprintf(outfile, "}\n");
+}
+
+void
+makePlanks()
+{
+       List planks;
+       renumber();
+       makePmaps();
+       planks = assemblePlanks();
+       purgePlanks(planks);
+       inToEx();
+       makePlankRule();
+       makePlankState();
+}
diff --git a/support/tools/Burg/queue.c b/support/tools/Burg/queue.c
new file mode 100644 (file)
index 0000000..76e5ea9
--- /dev/null
@@ -0,0 +1,64 @@
+char rcsid_queue[] = "$Id$";
+
+#include "b.h"
+#include <stdio.h>
+
+Queue globalQ;
+
+Queue
+newQ()
+{
+       Queue q;
+
+       q = (Queue) zalloc(sizeof(struct queue));
+       assert(q);
+       q->head = 0;
+       q->tail = 0;
+
+       return q;
+}
+
+void
+addQ(q, ts) Queue q; Item_Set ts;
+{
+       List qe;
+
+       assert(q);
+       assert(ts);
+
+       qe = newList(ts, 0);
+       if (q->head) {
+               assert(q->tail);
+               q->tail->next = qe;
+               q->tail = qe;
+       } else {
+               q->head = q->tail = qe;
+       }
+}
+
+Item_Set
+popQ(q) Queue q;
+{
+       List qe;
+       Item_Set ts;
+
+       assert(q);
+
+       if (q->head) {
+               qe = q->head;
+               q->head = q->head->next;
+               ts = (Item_Set) qe->x;
+               zfree(qe);
+               return ts;
+       } else {
+               return 0;
+       }
+}
+
+void
+dumpQ(q) Queue q;
+{
+       printf("Begin Queue\n");
+       foreachList((ListFn)dumpItem_Set, q->head);
+       printf("End Queue\n");
+}
diff --git a/support/tools/Burg/rule.c b/support/tools/Burg/rule.c
new file mode 100644 (file)
index 0000000..ee5c89e
--- /dev/null
@@ -0,0 +1,49 @@
+char rcsid_rule[] = "$Id$";
+
+#include "b.h"
+#include <stdio.h>
+
+RuleNum max_rule;
+int max_erule_num;
+
+struct rule stub_rule;
+
+List rules;
+
+Rule
+newRule(delta, erulenum, lhs, pat) DeltaPtr delta; ERuleNum erulenum; NonTerminal lhs; Pattern pat;
+{
+       Rule p;
+
+       p = (Rule) zalloc(sizeof(struct rule));
+       assert(p);
+       ASSIGNCOST(p->delta, delta);
+       p->erulenum = erulenum;
+       if (erulenum > max_erule_num) {
+               max_erule_num = erulenum;
+       }
+       p->num = max_rule++;
+       p->lhs = lhs;
+       p->pat = pat;
+
+       rules = newList(p, rules);
+
+       return p;
+}
+
+void
+dumpRule(p) Rule p;
+{
+       dumpNonTerminal(p->lhs);
+       printf(" : ");
+       dumpPattern(p->pat);
+       printf(" ");
+       dumpCost(p->delta);
+       printf("\n");
+}
+
+void
+dumpRuleList(l) List l;
+{
+       foreachList((ListFn)dumpRule, l);
+}
diff --git a/support/tools/Burg/sample.gr b/support/tools/Burg/sample.gr
new file mode 100644 (file)
index 0000000..e1f7283
--- /dev/null
@@ -0,0 +1,150 @@
+%{
+#include <stdio.h>
+
+typedef struct node *NODEPTR_TYPE;
+
+struct node {
+       int op, state_label;
+       NODEPTR_TYPE left, right;
+};
+
+#define OP_LABEL(p)    ((p)->op)
+#define STATE_LABEL(p) ((p)->state_label)
+#define LEFT_CHILD(p)  ((p)->left)
+#define RIGHT_CHILD(p) ((p)->right)
+#define PANIC          printf
+%}
+
+%start reg
+%term Assign=1 Constant=2 Fetch=3 Four=4 Mul=5 Plus=6
+%%
+con:  Constant                = 1 (0);
+con:  Four                    = 2 (0);
+addr: con                     = 3 (0);
+addr: Plus(con,reg)           = 4 (0);
+addr: Plus(con,Mul(Four,reg)) = 5 (0);
+reg:  Fetch(addr)             = 6 (1);
+reg:  Assign(addr,reg)        = 7 (1);
+
+%%
+
+#define Assign 1
+#define Constant 2
+#define Fetch 3
+#define Four 4
+#define Mul 5
+#define Plus 6
+
+#ifdef __STDC__
+#define ARGS(x) x
+#else
+#define ARGS(x) ()
+#endif
+
+NODEPTR_TYPE buildtree ARGS((int, NODEPTR_TYPE, NODEPTR_TYPE));
+void printcover ARGS((NODEPTR_TYPE, int, int));
+void printtree ARGS((NODEPTR_TYPE));
+int treecost ARGS((NODEPTR_TYPE, int, int));
+void printMatches ARGS((NODEPTR_TYPE));
+int main ARGS((void));
+
+NODEPTR_TYPE buildtree(op, left, right) int op; NODEPTR_TYPE left; NODEPTR_TYPE right; {
+       NODEPTR_TYPE p;
+       extern void *malloc ARGS((unsigned));
+
+       p = (NODEPTR_TYPE) malloc(sizeof *p);
+       p->op = op;
+       p->left = left;
+       p->right = right;
+       return p;
+}
+
+void printcover(p, goalnt, indent) NODEPTR_TYPE p; int goalnt; int indent; {
+       int eruleno = burm_rule(STATE_LABEL(p), goalnt);
+       short *nts = burm_nts[eruleno];
+       NODEPTR_TYPE kids[10];
+       int i;
+       
+       if (eruleno == 0) {
+               printf("no cover\n");
+               return;
+       }
+       for (i = 0; i < indent; i++)
+               printf(".");
+       printf("%s\n", burm_string[eruleno]);
+       burm_kids(p, eruleno, kids);
+       for (i = 0; nts[i]; i++)
+               printcover(kids[i], nts[i], indent+1);
+}
+
+void printtree(p) NODEPTR_TYPE p; {
+       int op = burm_op_label(p);
+
+       printf("%s", burm_opname[op]);
+       switch (burm_arity[op]) {
+       case 0:
+               break;
+       case 1:
+               printf("(");
+               printtree(burm_child(p, 0));
+               printf(")");
+               break;
+       case 2:
+               printf("(");
+               printtree(burm_child(p, 0));
+               printf(", ");
+               printtree(burm_child(p, 1));
+               printf(")");
+               break;
+       }
+}
+
+int treecost(p, goalnt, costindex) NODEPTR_TYPE p; int goalnt; int costindex; {
+       int eruleno = burm_rule(STATE_LABEL(p), goalnt);
+       int cost = burm_cost[eruleno][costindex], i;
+       short *nts = burm_nts[eruleno];
+       NODEPTR_TYPE kids[10];
+
+       burm_kids(p, eruleno, kids);
+       for (i = 0; nts[i]; i++)
+               cost += treecost(kids[i], nts[i], costindex);
+       return cost;
+}
+
+void printMatches(p) NODEPTR_TYPE p; {
+       int nt;
+       int eruleno;
+
+       printf("Node 0x%lx= ", (unsigned long)p);
+       printtree(p);
+       printf(" matched rules:\n");
+       for (nt = 1; burm_ntname[nt] != (char*)NULL; nt++)
+               if ((eruleno = burm_rule(STATE_LABEL(p), nt)) != 0)
+                       printf("\t%s\n", burm_string[eruleno]);
+}
+
+main() {
+       NODEPTR_TYPE p;
+
+       p = buildtree(Assign,
+               buildtree(Constant, 0, 0),
+               buildtree(Fetch,
+                       buildtree(Plus,
+                               buildtree(Constant, 0, 0),
+                               buildtree(Mul,
+                                       buildtree(Four, 0, 0),
+                                       buildtree(Fetch, buildtree(Constant, 0, 0), 0)
+                               )
+                       ),
+                       0
+               )
+       );
+       printtree(p);
+       printf("\n\n");
+       burm_label(p);
+       printcover(p, 1, 0);
+       printf("\nCover cost == %d\n\n", treecost(p, 1, 0));
+       printMatches(p);
+       return 0;
+}
+
diff --git a/support/tools/Burg/string.c b/support/tools/Burg/string.c
new file mode 100644 (file)
index 0000000..9b69c30
--- /dev/null
@@ -0,0 +1,65 @@
+char rcsid_string[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+#include "fe.h"
+
+static StrTableElement newStrTableElement ARGS((void));
+
+StrTable
+newStrTable()
+{
+       return (StrTable) zalloc(sizeof(struct strTable));
+}
+
+static StrTableElement
+newStrTableElement()
+{
+       return (StrTableElement) zalloc(sizeof(struct strTableElement));
+}
+
+void
+dumpStrTable(t) StrTable t;
+{ 
+       List e;
+       IntList r;
+
+       printf("Begin StrTable\n");
+       for (e = t->elems; e; e = e->next) {
+               StrTableElement el = (StrTableElement) e->x;
+               printf("%s: ", el->str);
+               for (r = el->erulenos; r; r = r->next) {
+                       int i = r->x;
+                       printf("(%d)", i);
+               }
+               printf("\n");
+       }
+       printf("End StrTable\n");
+}
+
+StrTableElement
+addString(t, s, eruleno, new) StrTable t; char *s; int eruleno; int *new;
+{
+       List l;
+       StrTableElement ste;
+
+       assert(t);
+       for (l = t->elems; l; l = l->next) {
+               StrTableElement e = (StrTableElement) l->x;
+
+               assert(e);
+               if (!strcmp(s, e->str)) {
+                       e->erulenos = newIntList(eruleno, e->erulenos);
+                       *new = 0;
+                       return e;
+               }
+       }
+       ste = newStrTableElement();
+       ste->erulenos = newIntList(eruleno, 0);
+       ste->str = (char *) zalloc(strlen(s) + 1);
+       strcpy(ste->str, s);
+       t->elems = newList(ste, t->elems);
+       *new = 1;
+       return ste;
+}
diff --git a/support/tools/Burg/symtab.c b/support/tools/Burg/symtab.c
new file mode 100644 (file)
index 0000000..3ecab2f
--- /dev/null
@@ -0,0 +1,38 @@
+char rcsid_symtab[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+#include "fe.h"
+
+static List symtab;
+
+Symbol
+newSymbol(name) char *name;
+{
+       Symbol s;
+
+       s = (Symbol) zalloc(sizeof(struct symbol));
+       assert(s);
+       s->name = name;
+       return s;
+}
+
+Symbol
+enter(name, new) char *name; int *new;
+{
+       List l;
+       Symbol s;
+
+       *new = 0;
+       for (l = symtab; l; l = l->next) {
+               s = (Symbol) l->x;
+               if (!strcmp(name, s->name)) {
+                       return s;
+               }
+       }
+       *new = 1;
+       s = newSymbol(name);
+       symtab = newList(s, symtab);
+       return s;
+}
diff --git a/support/tools/Burg/table.c b/support/tools/Burg/table.c
new file mode 100644 (file)
index 0000000..1de74f9
--- /dev/null
@@ -0,0 +1,552 @@
+char rcsid_table[] = "$Id$";
+
+#include "b.h"
+#include <string.h>
+#include <stdio.h>
+
+static void growIndex_Map ARGS((Index_Map *));
+static Relevant newRelevant ARGS((void));
+static Dimension newDimension ARGS((Operator, int));
+static void GT_1 ARGS((Table));
+static void GT_2_0 ARGS((Table));
+static void GT_2_1 ARGS((Table));
+static void growTransition ARGS((Table, int));
+static Item_Set restrict ARGS((Dimension, Item_Set));
+static void addHP_1 ARGS((Table, Item_Set));
+static void addHP_2_0 ARGS((Table, Item_Set));
+static void addHP_2_1 ARGS((Table, Item_Set));
+static void addHyperPlane ARGS((Table, int, Item_Set));
+
+static void
+growIndex_Map(r) Index_Map *r;
+{
+       Index_Map new;
+
+       new.max_size = r->max_size + STATES_INCR;
+       new.class = (Item_Set*) zalloc(new.max_size * sizeof(Item_Set));
+       assert(new.class);
+       memcpy(new.class, r->class, r->max_size * sizeof(Item_Set));
+       zfree(r->class);
+       *r = new;
+}
+
+static Relevant
+newRelevant()
+{
+       Relevant r = (Relevant) zalloc(max_nonterminal * sizeof(*r));
+       return r;
+}
+
+void
+addRelevant(r, nt) Relevant r; NonTerminalNum nt;
+{
+       int i;
+
+       for (i = 0; r[i]; i++) {
+               if (r[i] == nt) {
+                       break;
+               }
+       }
+       if (!r[i]) {
+               r[i] = nt;
+       }
+}
+
+static Dimension
+newDimension(op, index) Operator op; ArityNum index;
+{
+       Dimension d;
+       List pl;
+       Relevant r;
+
+       assert(op);
+       assert(index >= 0 && index < op->arity);
+       d = (Dimension) zalloc(sizeof(struct dimension));
+       assert(d);
+
+       r = d->relevant = newRelevant();
+       for (pl = rules; pl; pl = pl->next) {
+               Rule pr = (Rule) pl->x;
+               if (pr->pat->op == op) {
+                       addRelevant(r, pr->pat->children[index]->num);
+               }
+       }
+
+       d->index_map.max_size = STATES_INCR;
+       d->index_map.class = (Item_Set*) 
+                       zalloc(d->index_map.max_size * sizeof(Item_Set));
+       d->map = newMapping(DIM_MAP_SIZE);
+       d->max_size = TABLE_INCR;
+
+       return d;
+}
+
+Table
+newTable(op) Operator op;
+{
+       Table t;
+       int i, size;
+
+       assert(op);
+
+       t = (Table) zalloc(sizeof(struct table));
+       assert(t);
+
+       t->op = op;
+
+       for (i = 0; i < op->arity; i++) {
+               t->dimen[i] = newDimension(op, i);
+       }
+
+       size = 1;
+       for (i = 0; i < op->arity; i++) {
+               size *= t->dimen[i]->max_size;
+       }
+       t->transition = (Item_Set*) zalloc(size * sizeof(Item_Set));
+       t->relevant = newRelevant();
+       assert(t->transition);
+
+       return t;
+}
+
+static void
+GT_1(t) Table t;
+{
+       Item_Set        *ts;
+       ItemSetNum      oldsize = t->dimen[0]->max_size;
+       ItemSetNum      newsize = t->dimen[0]->max_size + TABLE_INCR;
+
+       t->dimen[0]->max_size = newsize;
+
+       ts = (Item_Set*) zalloc(newsize * sizeof(Item_Set));
+       assert(ts);
+       memcpy(ts, t->transition, oldsize * sizeof(Item_Set));
+       zfree(t->transition);
+       t->transition = ts;
+}
+
+static void
+GT_2_0(t) Table t;
+{
+       Item_Set        *ts;
+       ItemSetNum      oldsize = t->dimen[0]->max_size;
+       ItemSetNum      newsize = t->dimen[0]->max_size + TABLE_INCR;
+       int             size;
+
+       t->dimen[0]->max_size = newsize;
+
+       size = newsize * t->dimen[1]->max_size;
+
+       ts = (Item_Set*) zalloc(size * sizeof(Item_Set));
+       assert(ts);
+       memcpy(ts, t->transition, oldsize*t->dimen[1]->max_size * sizeof(Item_Set));
+       zfree(t->transition);
+       t->transition = ts;
+}
+
+static void
+GT_2_1(t) Table t;
+{
+       Item_Set        *ts;
+       ItemSetNum      oldsize = t->dimen[1]->max_size;
+       ItemSetNum      newsize = t->dimen[1]->max_size + TABLE_INCR;
+       int             size;
+       Item_Set        *from;
+       Item_Set        *to;
+       int             i1, i2;
+
+       t->dimen[1]->max_size = newsize;
+
+       size = newsize * t->dimen[0]->max_size;
+
+       ts = (Item_Set*) zalloc(size * sizeof(Item_Set));
+       assert(ts);
+
+       from = t->transition;
+       to = ts;
+       for (i1 = 0; i1 < t->dimen[0]->max_size; i1++) {
+               for (i2 = 0; i2 < oldsize; i2++) {
+                       to[i2] = from[i2];
+               }
+               to += newsize;
+               from += oldsize;
+       }
+       zfree(t->transition);
+       t->transition = ts;
+}
+
+static void
+growTransition(t, dim) Table t; ArityNum dim;
+{
+
+       assert(t);
+       assert(t->op);
+       assert(dim < t->op->arity);
+
+       switch (t->op->arity) {
+       default:
+               assert(0);
+               break;
+       case 1:
+               GT_1(t);
+               return;
+       case 2:
+               switch (dim) {
+               default:
+                       assert(0);
+                       break;
+               case 0:
+                       GT_2_0(t);
+                       return;
+               case 1:
+                       GT_2_1(t);
+                       return;
+               }
+       }
+}
+
+static Item_Set
+restrict(d, ts) Dimension d; Item_Set ts;
+{
+       DeltaCost       base;
+       Item_Set        r;
+       int found;
+       register Relevant r_ptr = d->relevant;
+       register Item *ts_current = ts->closed;
+       register Item *r_current;
+       register int i;
+       register int nt;
+
+       ZEROCOST(base);
+       found = 0;
+       r = newItem_Set(d->relevant);
+       r_current = r->virgin;
+       for (i = 0; (nt = r_ptr[i]) != 0; i++) {
+               if (ts_current[nt].rule) {
+                       r_current[nt].rule = &stub_rule;
+                       if (!found) {
+                               found = 1;
+                               ASSIGNCOST(base, ts_current[nt].delta);
+                       } else {
+                               if (LESSCOST(ts_current[nt].delta, base)) {
+                                       ASSIGNCOST(base, ts_current[nt].delta);
+                               }
+                       }
+               }
+       }
+
+       /* zero align */
+       for (i = 0; (nt = r_ptr[i]) != 0; i++) {
+               if (r_current[nt].rule) {
+                       ASSIGNCOST(r_current[nt].delta, ts_current[nt].delta);
+                       MINUSCOST(r_current[nt].delta, base);
+               }
+       }
+       assert(!r->closed);
+       r->representative = ts;
+       return r;
+}
+
+static void
+addHP_1(t, ts) Table t; Item_Set ts;
+{
+       List pl;
+       Item_Set e;
+       Item_Set tmp;
+       int new;
+
+       e = newItem_Set(t->relevant);
+       assert(e);
+       e->kids[0] = ts->representative;
+       for (pl = t->rules; pl; pl = pl->next) {
+               Rule p = (Rule) pl->x;
+               if (t->op == p->pat->op && ts->virgin[p->pat->children[0]->num].rule) {
+                       DeltaCost dc;
+                       ASSIGNCOST(dc, ts->virgin[p->pat->children[0]->num].delta);
+                       ADDCOST(dc, p->delta);
+                       if (!e->virgin[p->lhs->num].rule || LESSCOST(dc, e->virgin[p->lhs->num].delta)) {
+                               e->virgin[p->lhs->num].rule = p;
+                               ASSIGNCOST(e->virgin[p->lhs->num].delta, dc);
+                               e->op = t->op;
+                       }
+               }
+       }
+       trim(e);
+       zero(e);
+       tmp = encode(globalMap, e, &new);
+       assert(ts->num < t->dimen[0]->map->max_size);
+       t->transition[ts->num] = tmp;
+       if (new) {
+               closure(e);
+               addQ(globalQ, tmp);
+       } else {
+               freeItem_Set(e);
+       }
+}
+
+static void
+addHP_2_0(t, ts) Table t; Item_Set ts;
+{
+       List pl;
+       register Item_Set e;
+       Item_Set tmp;
+       int new;
+       int i2;
+
+       assert(t->dimen[1]->map->count <= t->dimen[1]->map->max_size);
+       for (i2 = 0; i2 < t->dimen[1]->map->count; i2++) {
+               e = newItem_Set(t->relevant);
+               assert(e);
+               e->kids[0] = ts->representative;
+               e->kids[1] = t->dimen[1]->map->set[i2]->representative;
+               for (pl = t->rules; pl; pl = pl->next) {
+                       register Rule p = (Rule) pl->x;
+
+                       if (t->op == p->pat->op 
+                                       && ts->virgin[p->pat->children[0]->num].rule
+                                       && t->dimen[1]->map->set[i2]->virgin[p->pat->children[1]->num].rule){
+                               DeltaCost dc;
+                               ASSIGNCOST(dc, p->delta);
+                               ADDCOST(dc, ts->virgin[p->pat->children[0]->num].delta);
+                               ADDCOST(dc, t->dimen[1]->map->set[i2]->virgin[p->pat->children[1]->num].delta);
+
+                               if (!e->virgin[p->lhs->num].rule || LESSCOST(dc, e->virgin[p->lhs->num].delta)) {
+                                       e->virgin[p->lhs->num].rule = p;
+                                       ASSIGNCOST(e->virgin[p->lhs->num].delta, dc);
+                                       e->op = t->op;
+                               }
+                       }
+               }
+               trim(e);
+               zero(e);
+               tmp = encode(globalMap, e, &new);
+               assert(ts->num < t->dimen[0]->map->max_size);
+               t->transition[ts->num * t->dimen[1]->max_size + i2] = tmp;
+               if (new) {
+                       closure(e);
+                       addQ(globalQ, tmp);
+               } else {
+                       freeItem_Set(e);
+               }
+       }
+}
+
+static void
+addHP_2_1(t, ts) Table t; Item_Set ts;
+{
+       List pl;
+       register Item_Set e;
+       Item_Set tmp;
+       int new;
+       int i1;
+
+       assert(t->dimen[0]->map->count <= t->dimen[0]->map->max_size);
+       for (i1 = 0; i1 < t->dimen[0]->map->count; i1++) {
+               e = newItem_Set(t->relevant);
+               assert(e);
+               e->kids[0] = t->dimen[0]->map->set[i1]->representative;
+               e->kids[1] = ts->representative;
+               for (pl = t->rules; pl; pl = pl->next) {
+                       register Rule p = (Rule) pl->x;
+
+                       if (t->op == p->pat->op 
+                                       && ts->virgin[p->pat->children[1]->num].rule
+                                       && t->dimen[0]->map->set[i1]->virgin[p->pat->children[0]->num].rule){
+                               DeltaCost dc;
+                               ASSIGNCOST(dc, p->delta );
+                               ADDCOST(dc, ts->virgin[p->pat->children[1]->num].delta);
+                               ADDCOST(dc, t->dimen[0]->map->set[i1]->virgin[p->pat->children[0]->num].delta);
+                               if (!e->virgin[p->lhs->num].rule || LESSCOST(dc, e->virgin[p->lhs->num].delta)) {
+                                       e->virgin[p->lhs->num].rule = p;
+                                       ASSIGNCOST(e->virgin[p->lhs->num].delta, dc);
+                                       e->op = t->op;
+                               }
+                       }
+               }
+               trim(e);
+               zero(e);
+               tmp = encode(globalMap, e, &new);
+               assert(ts->num < t->dimen[1]->map->max_size);
+               t->transition[i1 * t->dimen[1]->max_size + ts->num] = tmp;
+               if (new) {
+                       closure(e);
+                       addQ(globalQ, tmp);
+               } else {
+                       freeItem_Set(e);
+               }
+       }
+}
+
+static void
+addHyperPlane(t, i, ts) Table t; ArityNum i; Item_Set ts;
+{
+       switch (t->op->arity) {
+       default:
+               assert(0);
+               break;
+       case 1:
+               addHP_1(t, ts);
+               return;
+       case 2:
+               switch (i) {
+               default:
+                       assert(0);
+                       break;
+               case 0:
+                       addHP_2_0(t, ts);
+                       return;
+               case 1:
+                       addHP_2_1(t, ts);
+                       return;
+               }
+       }
+}
+
+void
+addToTable(t, ts) Table t; Item_Set ts;
+{
+       ArityNum i;
+
+       assert(t);
+       assert(ts);
+       assert(t->op);
+
+       for (i = 0; i < t->op->arity; i++) {
+               Item_Set r;
+               Item_Set tmp;
+               int new;
+
+               r = restrict(t->dimen[i], ts);
+               tmp = encode(t->dimen[i]->map, r, &new);
+               if (t->dimen[i]->index_map.max_size <= ts->num) {
+                       growIndex_Map(&t->dimen[i]->index_map);
+               }
+               assert(ts->num < t->dimen[i]->index_map.max_size);
+               t->dimen[i]->index_map.class[ts->num] = tmp;
+               if (new) {
+                       if (t->dimen[i]->max_size <= r->num) {
+                               growTransition(t, i);
+                       }
+                       addHyperPlane(t, i, r);
+               } else {
+                       freeItem_Set(r);
+               }
+       }
+}
+
+Item_Set *
+transLval(t, row, col) Table t; int row; int col;
+{
+       switch (t->op->arity) {
+       case 0:
+               assert(row == 0);
+               assert(col == 0);
+               return t->transition;
+       case 1:
+               assert(col == 0);
+               return t->transition + row;
+       case 2:
+               return t->transition + row * t->dimen[1]->max_size + col;
+       default:
+               assert(0);
+       }
+       return 0;
+}
+
+void
+dumpRelevant(r) Relevant r;
+{
+       for (; *r; r++) {
+               printf("%4d", *r);
+       }
+}
+
+void
+dumpIndex_Map(r) Index_Map *r;
+{
+       int i;
+
+       printf("BEGIN Index_Map: MaxSize (%d)\n", r->max_size);
+       for (i = 0; i < globalMap->count; i++) {
+               printf("\t#%d: -> %d\n", i, r->class[i]->num);
+       }
+       printf("END Index_Map:\n");
+}
+
+void
+dumpDimension(d) Dimension d;
+{
+       printf("BEGIN Dimension:\n");
+       printf("Relevant: ");
+       dumpRelevant(d->relevant);
+       printf("\n");
+       dumpIndex_Map(&d->index_map);
+       dumpMapping(d->map);
+       printf("MaxSize of dimension = %d\n", d->max_size);
+       printf("END Dimension\n");
+}
+
+void
+dumpTable(t, full) Table t; int full;
+{
+       int i;
+
+       if (!t) {
+               printf("NO Table yet.\n");
+               return;
+       }
+       printf("BEGIN Table:\n");
+       if (full) {
+               dumpOperator(t->op, 0);
+       }
+       for (i = 0; i < t->op->arity; i++) {
+               printf("BEGIN dimension(%d)\n", i);
+               dumpDimension(t->dimen[i]);
+               printf("END dimension(%d)\n", i);
+       }
+       dumpTransition(t);
+       printf("END Table:\n");
+}
+
+void
+dumpTransition(t) Table t;
+{
+       int i,j;
+
+       switch (t->op->arity) {
+       case 0:
+               printf("{ %d }", t->transition[0]->num);
+               break;
+       case 1:
+               printf("{");
+               for (i = 0; i < t->dimen[0]->map->count; i++) {
+                       if (i > 0) {
+                               printf(",");
+                       }
+                       printf("%5d", t->transition[i]->num);
+               }
+               printf("}");
+               break;
+       case 2:
+               printf("{");
+               for (i = 0; i < t->dimen[0]->map->count; i++) {
+                       if (i > 0) {
+                               printf(",");
+                       }
+                       printf("\n");
+                       printf("{");
+                       for (j = 0; j < t->dimen[1]->map->count; j++) {
+                               Item_Set *ts = transLval(t, i, j);
+                               if (j > 0) {
+                                       printf(",");
+                               }
+                               printf("%5d", (*ts)->num);
+                       }
+                       printf("}");
+               }
+               printf("\n}\n");
+               break;
+       default:
+               assert(0);
+       }
+}
diff --git a/support/tools/Burg/trim.c b/support/tools/Burg/trim.c
new file mode 100644 (file)
index 0000000..05ee2d0
--- /dev/null
@@ -0,0 +1,412 @@
+char rcsid_trim[] = "$Id$";
+
+#include <stdio.h>
+#include "b.h"
+#include "fe.h"
+
+Relation *allpairs;
+
+int trimflag = 0;
+int debugTrim = 0;
+
+static void siblings ARGS((int, int));
+static void findAllNexts ARGS((void));
+static Relation *newAllPairs ARGS((void));
+
+static void
+siblings(i, j) int i; int j;
+{
+       int k;
+       List pl;
+       DeltaCost Max;
+       int foundmax;
+
+       allpairs[i][j].sibComputed = 1;
+
+       if (i == 1) {
+               return; /* never trim start symbol */
+       }
+       if (i==j) {
+               return;
+       }
+
+       ZEROCOST(Max);
+       foundmax = 0;
+
+       for (k = 1; k < max_nonterminal; k++) {
+               DeltaCost tmp;
+
+               if (k==i || k==j) {
+                       continue;
+               }
+               if (!allpairs[k][i].rule) {
+                       continue;
+               }
+               if (!allpairs[k][j].rule) {
+                       return;
+               }
+               ASSIGNCOST(tmp, allpairs[k][j].chain);
+               MINUSCOST(tmp, allpairs[k][i].chain);
+               if (foundmax) {
+                       if (LESSCOST(Max, tmp)) {
+                               ASSIGNCOST(Max, tmp);
+                       }
+               } else {
+                       foundmax = 1;
+                       ASSIGNCOST(Max, tmp);
+               }
+       }
+
+       for (pl = rules; pl; pl = pl->next) {
+               Rule p = (Rule) pl->x;
+               Operator op = p->pat->op;
+               List oprule;
+               DeltaCost Min;
+               int foundmin;
+               
+               if (!op) {
+                       continue;
+               }
+               switch (op->arity) {
+               case 0:
+                       continue;
+               case 1:
+                       if (!allpairs[p->pat->children[0]->num ][ i].rule) {
+                               continue;
+                       }
+                       foundmin = 0;
+                       for (oprule = op->table->rules; oprule; oprule = oprule->next) {
+                               Rule s = (Rule) oprule->x;
+                               DeltaPtr Cx;
+                               DeltaPtr Csj;
+                               DeltaPtr Cpi;
+                               DeltaCost tmp;
+
+                               if (!allpairs[p->lhs->num ][ s->lhs->num].rule
+                                || !allpairs[s->pat->children[0]->num ][ j].rule) {
+                                       continue;
+                               }
+                               Cx = allpairs[p->lhs->num ][ s->lhs->num].chain;
+                               Csj= allpairs[s->pat->children[0]->num ][ j].chain;
+                               Cpi= allpairs[p->pat->children[0]->num ][ i].chain;
+                               ASSIGNCOST(tmp, Cx);
+                               ADDCOST(tmp, s->delta);
+                               ADDCOST(tmp, Csj);
+                               MINUSCOST(tmp, Cpi);
+                               MINUSCOST(tmp, p->delta);
+                               if (foundmin) {
+                                       if (LESSCOST(tmp, Min)) {
+                                               ASSIGNCOST(Min, tmp);
+                                       }
+                               } else {
+                                       foundmin = 1;
+                                       ASSIGNCOST(Min, tmp);
+                               }
+                       }
+                       if (!foundmin) {
+                               return;
+                       }
+                       if (foundmax) {
+                               if (LESSCOST(Max, Min)) {
+                                       ASSIGNCOST(Max, Min);
+                               }
+                       } else {
+                               foundmax = 1;
+                               ASSIGNCOST(Max, Min);
+                       }
+                       break;
+               case 2:
+               /* do first dimension */
+               if (allpairs[p->pat->children[0]->num ][ i].rule) {
+                       foundmin = 0;
+                       for (oprule = op->table->rules; oprule; oprule = oprule->next) {
+                               Rule s = (Rule) oprule->x;
+                               DeltaPtr Cx;
+                               DeltaPtr Cb;
+                               DeltaPtr Csj;
+                               DeltaPtr Cpi;
+                               DeltaCost tmp;
+
+                               if (allpairs[p->lhs->num ][ s->lhs->num].rule
+                                && allpairs[s->pat->children[0]->num ][ j].rule
+                                && allpairs[s->pat->children[1]->num ][ p->pat->children[1]->num].rule) {
+                                       Cx = allpairs[p->lhs->num ][ s->lhs->num].chain;
+                                       Csj= allpairs[s->pat->children[0]->num ][ j].chain;
+                                       Cpi= allpairs[p->pat->children[0]->num ][ i].chain;
+                                       Cb = allpairs[s->pat->children[1]->num ][ p->pat->children[1]->num].chain;
+                                       ASSIGNCOST(tmp, Cx);
+                                       ADDCOST(tmp, s->delta);
+                                       ADDCOST(tmp, Csj);
+                                       ADDCOST(tmp, Cb);
+                                       MINUSCOST(tmp, Cpi);
+                                       MINUSCOST(tmp, p->delta);
+                                       if (foundmin) {
+                                               if (LESSCOST(tmp, Min)) {
+                                                       ASSIGNCOST(Min, tmp);
+                                               }
+                                       } else {
+                                               foundmin = 1;
+                                               ASSIGNCOST(Min, tmp);
+                                       }
+                               }
+                       }
+                       if (!foundmin) {
+                               return;
+                       }
+                       if (foundmax) {
+                               if (LESSCOST(Max, Min)) {
+                                       ASSIGNCOST(Max, Min);
+                               }
+                       } else {
+                               foundmax = 1;
+                               ASSIGNCOST(Max, Min);
+                       }
+               }
+               /* do second dimension */
+               if (allpairs[p->pat->children[1]->num ][ i].rule) {
+                       foundmin = 0;
+                       for (oprule = op->table->rules; oprule; oprule = oprule->next) {
+                               Rule s = (Rule) oprule->x;
+                               DeltaPtr Cx;
+                               DeltaPtr Cb;
+                               DeltaPtr Csj;
+                               DeltaPtr Cpi;
+                               DeltaCost tmp;
+
+                               if (allpairs[p->lhs->num ][ s->lhs->num].rule
+                                && allpairs[s->pat->children[1]->num ][ j].rule
+                                && allpairs[s->pat->children[0]->num ][ p->pat->children[0]->num].rule) {
+                                       Cx = allpairs[p->lhs->num ][ s->lhs->num].chain;
+                                       Csj= allpairs[s->pat->children[1]->num ][ j].chain;
+                                       Cpi= allpairs[p->pat->children[1]->num ][ i].chain;
+                                       Cb = allpairs[s->pat->children[0]->num ][ p->pat->children[0]->num].chain;
+                                       ASSIGNCOST(tmp, Cx);
+                                       ADDCOST(tmp, s->delta);
+                                       ADDCOST(tmp, Csj);
+                                       ADDCOST(tmp, Cb);
+                                       MINUSCOST(tmp, Cpi);
+                                       MINUSCOST(tmp, p->delta);
+                                       if (foundmin) {
+                                               if (LESSCOST(tmp, Min)) {
+                                                       ASSIGNCOST(Min, tmp);
+                                               }
+                                       } else {
+                                               foundmin = 1;
+                                               ASSIGNCOST(Min, tmp);
+                                       }
+                               }
+                       }
+                       if (!foundmin) {
+                               return;
+                       }
+                       if (foundmax) {
+                               if (LESSCOST(Max, Min)) {
+                                       ASSIGNCOST(Max, Min);
+                               }
+                       } else {
+                               foundmax = 1;
+                               ASSIGNCOST(Max, Min);
+                       }
+               }
+               break;
+               default:
+                       assert(0);
+               }
+       }
+       allpairs[i ][ j].sibFlag = foundmax;
+       ASSIGNCOST(allpairs[i ][ j].sibling, Max);
+}
+
+static void
+findAllNexts()
+{
+       int i,j;
+       int last;
+
+       for (i = 1; i < max_nonterminal; i++) {
+               last = 0;
+               for (j = 1; j < max_nonterminal; j++) {
+                       if (allpairs[i ][j].rule) {
+                               allpairs[i ][ last].nextchain = j;
+                               last = j;
+                       }
+               }
+       }
+       /*
+       for (i = 1; i < max_nonterminal; i++) {
+               last = 0;
+               for (j = 1; j < max_nonterminal; j++) {
+                       if (allpairs[i ][j].sibFlag) {
+                               allpairs[i ][ last].nextsibling = j;
+                               last = j;
+                       }
+               }
+       }
+       */
+}
+
+static Relation *
+newAllPairs()
+{
+       int i;
+       Relation *rv;
+
+       rv = (Relation*) zalloc(max_nonterminal * sizeof(Relation));
+       for (i = 0; i < max_nonterminal; i++) {
+               rv[i] = (Relation) zalloc(max_nonterminal * sizeof(struct relation));
+       }
+       return rv;
+}
+
+void
+findAllPairs()
+{
+       List pl;
+       int changes;
+       int j;
+
+       allpairs = newAllPairs();
+       for (pl = chainrules; pl; pl = pl->next) {
+               Rule p = (Rule) pl->x;
+               NonTerminalNum rhs = p->pat->children[0]->num;
+               NonTerminalNum lhs = p->lhs->num;
+               Relation r = &allpairs[lhs ][ rhs];
+
+               if (LESSCOST(p->delta, r->chain)) {
+                       ASSIGNCOST(r->chain, p->delta);
+                       r->rule = p;
+               }
+       }
+       for (j = 1; j < max_nonterminal; j++) {
+               Relation r = &allpairs[j ][ j];
+               ZEROCOST(r->chain);
+               r->rule = &stub_rule;
+       }
+       changes = 1;
+       while (changes) {
+               changes = 0;
+               for (pl = chainrules; pl; pl = pl->next) {
+                       Rule p = (Rule) pl->x;
+                       NonTerminalNum rhs = p->pat->children[0]->num;
+                       NonTerminalNum lhs = p->lhs->num;
+                       int i;
+
+                       for (i = 1; i < max_nonterminal; i++) {
+                               Relation r = &allpairs[rhs ][ i];
+                               Relation s = &allpairs[lhs ][ i];
+                               DeltaCost dc;
+                               if (!r->rule) {
+                                       continue;
+                               }
+                               ASSIGNCOST(dc, p->delta);
+                               ADDCOST(dc, r->chain);
+                               if (!s->rule || LESSCOST(dc, s->chain)) {
+                                       s->rule = p;
+                                       ASSIGNCOST(s->chain, dc);
+                                       changes = 1;
+                               }
+                       }
+               }
+       }
+       findAllNexts();
+}
+
+void
+trim(t) Item_Set t;
+{
+       int m,n;
+       static short *vec = 0;
+       int last;
+
+       assert(!t->closed);
+       debug(debugTrim, printf("Begin Trim\n"));
+       debug(debugTrim, dumpItem_Set(t));
+
+       last = 0;
+       if (!vec) {
+               vec = (short*) zalloc(max_nonterminal * sizeof(*vec));
+       }
+       for (m = 1; m < max_nonterminal; m++) {
+               if (t->virgin[m].rule) {
+                       vec[last++] = m;
+               }
+       }
+       for (m = 0; m < last; m++) {
+               DeltaCost tmp;
+               int j;
+               int i;
+
+               i = vec[m];
+
+               for (j = allpairs[i ][ 0].nextchain; j; j = allpairs[i ][ j].nextchain) {
+
+                       if (i == j) {
+                               continue;
+                       }
+                       if (!t->virgin[j].rule) {
+                               continue;
+                       }
+                       ASSIGNCOST(tmp, t->virgin[j].delta);
+                       ADDCOST(tmp, allpairs[i ][ j].chain);
+                       if (!LESSCOST(t->virgin[i].delta, tmp)) {
+                               t->virgin[i].rule = 0;
+                               ZEROCOST(t->virgin[i].delta);
+                               debug(debugTrim, printf("Trimmed Chain (%d,%d)\n", i,j));
+                               goto outer;
+                       }
+                       
+               }
+               if (!trimflag) {
+                       continue;
+               }
+               for (n = 0; n < last; n++) {
+                       j = vec[n];
+                       if (i == j) {
+                               continue;
+                       }
+
+                       if (!t->virgin[j].rule) {
+                               continue;
+                       }
+
+                       if (!allpairs[i][j].sibComputed) {
+                               siblings(i,j);
+                       }
+                       if (!allpairs[i][j].sibFlag) {
+                               continue;
+                       }
+                       ASSIGNCOST(tmp, t->virgin[j].delta);
+                       ADDCOST(tmp, allpairs[i ][ j].sibling);
+                       if (!LESSCOST(t->virgin[i].delta, tmp)) {
+                               t->virgin[i].rule = 0;
+                               ZEROCOST(t->virgin[i].delta);
+                               goto outer;
+                       }
+               }
+
+               outer: ;
+       }
+
+       debug(debugTrim, dumpItem_Set(t));
+       debug(debugTrim, printf("End Trim\n"));
+}
+
+void
+dumpRelation(r) Relation r;
+{
+       printf("{ %d %ld %d %ld }", r->rule->erulenum, (long) r->chain, r->sibFlag, (long) r->sibling);
+}
+
+void
+dumpAllPairs()
+{
+       int i,j;
+
+       printf("Dumping AllPairs\n");
+       for (i = 1; i < max_nonterminal; i++) {
+               for (j = 1; j < max_nonterminal; j++) {
+                       dumpRelation(&allpairs[i ][j]);
+               }
+               printf("\n");
+       }
+}
diff --git a/support/tools/Burg/zalloc.c b/support/tools/Burg/zalloc.c
new file mode 100644 (file)
index 0000000..bd50217
--- /dev/null
@@ -0,0 +1,35 @@
+char rcsid_zalloc[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+
+extern void exit ARGS((int));
+extern void free ARGS((void *));
+extern void *malloc ARGS((unsigned));
+
+int
+fatal(name, line) char *name; int line;
+{
+       fprintf(stderr, "assertion failed: file %s, line %d\n", name, line);
+       exit(1);
+       return 0;
+}
+
+void *
+zalloc(size) unsigned int size;
+{
+       void *t = (void *) malloc(size);
+       if (!t) {
+               fprintf(stderr, "Malloc failed---PROGRAM ABORTED\n");
+               exit(1);
+       }
+       memset(t, 0, size);
+       return t;
+}
+
+void
+zfree(p) void *p;
+{
+       free(p);
+}
diff --git a/utils/Burg/COPYRIGHT b/utils/Burg/COPYRIGHT
new file mode 100644 (file)
index 0000000..1de0aad
--- /dev/null
@@ -0,0 +1,13 @@
+Copyright (C) 1991 Todd A. Proebsting
+All Rights Reserved.
+
+This software is in the public domain.  You may use and copy this material
+freely. This privilege extends to modifications, although any modified
+version of this system given to a third party should clearly identify your
+modifications as well as the original source.
+
+The responsibility for the use of this material resides entirely with you.
+We make no warranty of any kind concerning this material, nor do we make
+any claim as to the suitability of BURG for any application.  This software
+is experimental in nature and there is no written or implied warranty.  Use
+it at your own risk.
diff --git a/utils/Burg/LOG_CHANGES b/utils/Burg/LOG_CHANGES
new file mode 100644 (file)
index 0000000..a7ee343
--- /dev/null
@@ -0,0 +1,2 @@
+8/20/02 -- Vikram Adve
+       be.c: Replaced "char*" with "const char*" to avoid compiler warnings.
diff --git a/utils/Burg/Makefile b/utils/Burg/Makefile
new file mode 100644 (file)
index 0000000..226210d
--- /dev/null
@@ -0,0 +1,84 @@
+# $Id$
+
+#CFLAGS        =
+#CFLAGS        = -O
+#CFLAGS        = -O -DNOLEX
+CFLAGS = -g -DDEBUG
+#CFLAGS        = -g -DNOLEX -DDEBUG
+
+SRCS = \
+       be.c \
+       burs.c \
+       closure.c \
+       delta.c \
+       fe.c \
+       item.c \
+       lex.c \
+       list.c \
+       main.c \
+       map.c \
+       nonterminal.c \
+       operator.c \
+       pattern.c \
+       plank.c \
+       queue.c \
+       rule.c \
+       string.c \
+       symtab.c \
+       table.c \
+       trim.c \
+       zalloc.c
+
+BU_OBJS = \
+       burs.o \
+       closure.o \
+       delta.o \
+       item.o \
+       list.o \
+       map.o \
+       nonterminal.o \
+       operator.o \
+       pattern.o \
+       queue.o \
+       rule.o \
+       table.o \
+       trim.o \
+       zalloc.o
+
+FE_OBJS = \
+       be.o \
+       fe.o \
+       lex.o \
+       main.o \
+       plank.o \
+       string.o \
+       symtab.o \
+       y.tab.o
+
+all: test
+
+burg: $(BU_OBJS) $(FE_OBJS)
+       $(CC) -o burg $(CFLAGS) $(BU_OBJS) $(FE_OBJS)
+
+y.tab.c y.tab.h: gram.y
+       yacc -d gram.y
+
+clean:
+       rm -f *.o y.tab.h y.tab.c core burg *.aux *.log *.dvi sample sample.c tmp
+
+$(FE_OBJS):    b.h
+$(BU_OBJS):    b.h
+$(FE_OBJS):    fe.h
+
+lex.o: y.tab.h
+
+doc.dvi: doc.tex
+       latex doc; latex doc
+
+test: burg sample.gr
+       ./burg -I     <sample.gr   >sample.c && cc $(CFLAGS) -o sample sample.c && ./sample
+       ./burg -I      sample.gr   >tmp && cmp tmp sample.c
+       ./burg -I     <sample.gr -o tmp && cmp tmp sample.c
+       ./burg -I      sample.gr -o tmp && cmp tmp sample.c
+       ./burg -I -O0 <sample.gr   >tmp && cmp tmp sample.c
+       ./burg -I -=  <sample.gr   >tmp && cmp tmp sample.c
diff --git a/utils/Burg/README b/utils/Burg/README
new file mode 100644 (file)
index 0000000..bc26405
--- /dev/null
@@ -0,0 +1,14 @@
+To format the documentation, type "make doc.dvi" and print the result.
+
+The length of the cost vectors is fixed at 4 for reasons that are
+primarily historical.  To change it, edit the definition of DELTAWIDTH
+in b.h.
+
+Burg is compiled without optimization by default to avoid problems
+with initial installation.  To improve burg's performance, add '-O' to
+CFLAGS in the Makefile and rebuild burg with a high quality optimizing
+compiler.
+
+To be added to the Burg mailing list, send your preferred electronic
+mail address to cwf@research.att.com.
+
diff --git a/utils/Burg/b.h b/utils/Burg/b.h
new file mode 100644 (file)
index 0000000..f1b33ed
--- /dev/null
@@ -0,0 +1,311 @@
+/* $Id$ */
+
+#define MAX_ARITY      2
+
+typedef int ItemSetNum;
+typedef int OperatorNum;
+typedef int NonTerminalNum;
+typedef int RuleNum;
+typedef int ArityNum;
+typedef int ERuleNum;
+
+extern NonTerminalNum  last_user_nonterminal;
+extern NonTerminalNum  max_nonterminal;
+extern RuleNum         max_rule;
+extern ERuleNum                max_erule_num;
+extern int             max_arity;
+
+#ifdef __STDC__
+#define ARGS(x) x
+#else
+#define ARGS(x) ()
+#endif
+
+#ifndef NOLEX
+#define DELTAWIDTH     4
+typedef short DeltaCost[DELTAWIDTH];
+typedef short *DeltaPtr;
+extern void ASSIGNCOST ARGS((DeltaPtr, DeltaPtr));
+extern void ADDCOST ARGS((DeltaPtr, DeltaPtr));
+extern void MINUSCOST ARGS((DeltaPtr, DeltaPtr));
+extern void ZEROCOST ARGS((DeltaPtr));
+extern int LESSCOST ARGS((DeltaPtr, DeltaPtr));
+extern int EQUALCOST ARGS((DeltaPtr, DeltaPtr));
+#define PRINCIPLECOST(x)       (x[0])
+#else
+#define DELTAWIDTH     1
+typedef int DeltaCost;
+typedef int DeltaPtr;
+#define ASSIGNCOST(l, r)       ((l) = (r))
+#define ADDCOST(l, r)          ((l) += (r))
+#define MINUSCOST(l, r)                ((l) -= (r))
+#define ZEROCOST(x)            ((x) = 0)
+#define LESSCOST(l, r)         ((l) < (r))
+#define EQUALCOST(l, r)                ((l) == (r))
+#define PRINCIPLECOST(x)       (x)
+#endif /* NOLEX */
+#define NODIVERGE(c,state,nt,base)             if (prevent_divergence > 0) CHECKDIVERGE(c,state,nt,base);
+
+struct list {
+       void            *x;
+       struct list     *next;
+};
+typedef struct list    *List;
+
+struct intlist {
+       int             x;
+       struct intlist  *next;
+};
+typedef struct intlist *IntList;
+
+struct operator {
+       char            *name;
+       unsigned int    ref:1;
+       OperatorNum     num;
+       ItemSetNum      baseNum;
+       ItemSetNum      stateCount;
+       ArityNum        arity;
+       struct table    *table;
+};
+typedef struct operator        *Operator;
+
+struct nonterminal {
+       char            *name;
+       NonTerminalNum  num;
+       ItemSetNum      baseNum;
+       ItemSetNum      ruleCount;
+       struct plankMap *pmap;
+
+       struct rule     *sampleRule; /* diagnostic---gives "a" rule that with this lhs */
+};
+typedef struct nonterminal     *NonTerminal;
+
+struct pattern {
+       NonTerminal     normalizer;
+       Operator        op;             /* NULL if NonTerm -> NonTerm */
+       NonTerminal     children[MAX_ARITY];
+};
+typedef struct pattern *Pattern;
+
+struct rule {
+       DeltaCost       delta;
+       ERuleNum        erulenum;
+       RuleNum         num;
+       RuleNum         newNum;
+       NonTerminal     lhs;
+       Pattern         pat;
+       unsigned int    used:1;
+};
+typedef struct rule    *Rule;
+
+struct item {
+       DeltaCost       delta;
+       Rule            rule;
+};
+typedef struct item    Item;
+
+typedef short  *Relevant;      /* relevant non-terminals */
+
+typedef Item   *ItemArray;
+
+struct item_set {      /* indexed by NonTerminal */
+       ItemSetNum      num;
+       ItemSetNum      newNum;
+       Operator        op;
+       struct item_set *kids[2];
+       struct item_set *representative;
+       Relevant        relevant;
+       ItemArray       virgin;
+       ItemArray       closed;
+};
+typedef struct item_set        *Item_Set;
+
+#define DIM_MAP_SIZE   (1 << 8)
+#define GLOBAL_MAP_SIZE        (1 << 15)
+
+struct mapping {       /* should be a hash table for TS -> int */
+       List            *hash;
+       int             hash_size;
+       int             max_size;
+       ItemSetNum      count;
+       Item_Set        *set;   /* map: int <-> Item_Set */
+};
+typedef struct mapping *Mapping;
+
+struct index_map {
+       ItemSetNum      max_size;
+       Item_Set        *class;
+};
+typedef struct index_map       Index_Map;
+
+struct dimension {
+       Relevant        relevant;
+       Index_Map       index_map;
+       Mapping         map;
+       ItemSetNum      max_size;
+       struct plankMap *pmap;
+};
+typedef struct dimension       *Dimension;
+
+
+struct table {
+       Operator        op;
+       List            rules;
+       Relevant        relevant;
+       Dimension       dimen[MAX_ARITY];       /* 1 for each dimension */
+       Item_Set        *transition;    /* maps local indices to global
+                                               itemsets */
+};
+typedef struct table   *Table;
+
+struct relation {
+       Rule    rule;
+       DeltaCost       chain;
+       NonTerminalNum  nextchain;
+       DeltaCost       sibling;
+       int             sibFlag;
+       int             sibComputed;
+};
+typedef struct relation        *Relation;
+
+struct queue {
+       List head;
+       List tail;
+};
+typedef struct queue   *Queue;
+
+struct plank {
+       char *name;
+       List fields;
+       int width;
+};
+typedef struct plank   *Plank;
+
+struct except {
+       short index;
+       short value;
+};
+typedef struct except  *Exception;
+
+struct plankMap {
+       List exceptions;
+       int offset;
+       struct stateMap *values;
+};
+typedef struct plankMap        *PlankMap;
+
+struct stateMap {
+       char *fieldname;
+       Plank plank;
+       int width;
+       short *value;
+};
+typedef struct stateMap        *StateMap;
+
+struct stateMapTable {
+       List maps;
+};
+
+extern void CHECKDIVERGE ARGS((DeltaPtr, Item_Set, int, int));
+extern void zero ARGS((Item_Set));
+extern ItemArray newItemArray ARGS((void));
+extern ItemArray itemArrayCopy ARGS((ItemArray));
+extern Item_Set newItem_Set ARGS((Relevant));
+extern void freeItem_Set ARGS((Item_Set));
+extern Mapping newMapping ARGS((int));
+extern NonTerminal newNonTerminal ARGS((char *));
+extern int nonTerminalName ARGS((char *, int));
+extern Operator newOperator ARGS((char *, OperatorNum, ArityNum));
+extern Pattern newPattern ARGS((Operator));
+extern Rule newRule ARGS((DeltaPtr, ERuleNum, NonTerminal, Pattern));
+extern List newList ARGS((void *, List));
+extern IntList newIntList ARGS((int, IntList));
+extern int length ARGS((List));
+extern List appendList ARGS((void *, List));
+extern Table newTable ARGS((Operator));
+extern Queue newQ ARGS((void));
+extern void addQ ARGS((Queue, Item_Set));
+extern Item_Set popQ ARGS((Queue));
+extern int equivSet ARGS((Item_Set, Item_Set));
+extern Item_Set decode ARGS((Mapping, ItemSetNum));
+extern Item_Set encode ARGS((Mapping, Item_Set, int *));
+extern void build ARGS((void));
+extern Item_Set *transLval ARGS((Table, int, int));
+
+typedef void * (*ListFn) ARGS((void *));
+extern void foreachList ARGS((ListFn, List));
+extern void reveachList ARGS((ListFn, List));
+
+extern void addToTable ARGS((Table, Item_Set));
+
+extern void closure ARGS((Item_Set));
+extern void trim ARGS((Item_Set));
+extern void findChainRules ARGS((void));
+extern void findAllPairs ARGS((void));
+extern void addRelevant ARGS((Relevant, NonTerminalNum));
+
+extern void *zalloc ARGS((unsigned int));
+extern void zfree ARGS((void *));
+
+extern NonTerminal     start;
+extern List            rules;
+extern List            chainrules;
+extern List            operators;
+extern List            leaves;
+extern List            nonterminals;
+extern List            grammarNts;
+extern Queue           globalQ;
+extern Mapping         globalMap;
+extern int             exceptionTolerance;
+extern int             prevent_divergence;
+extern int             principleCost;
+extern int             lexical;
+extern struct rule     stub_rule;
+extern Relation        *allpairs;
+extern Item_Set                *sortedStates;
+extern Item_Set                errorState;
+
+extern void dumpRelevant ARGS((Relevant));
+extern void dumpOperator ARGS((Operator, int));
+extern void dumpOperator_s ARGS((Operator));
+extern void dumpOperator_l ARGS((Operator));
+extern void dumpNonTerminal ARGS((NonTerminal));
+extern void dumpRule ARGS((Rule));
+extern void dumpRuleList ARGS((List));
+extern void dumpItem ARGS((Item *));
+extern void dumpItem_Set ARGS((Item_Set));
+extern void dumpMapping ARGS((Mapping));
+extern void dumpQ ARGS((Queue));
+extern void dumpIndex_Map ARGS((Index_Map *));
+extern void dumpDimension ARGS((Dimension));
+extern void dumpPattern ARGS((Pattern));
+extern void dumpTable ARGS((Table, int));
+extern void dumpTransition ARGS((Table));
+extern void dumpCost ARGS((DeltaCost));
+extern void dumpAllPairs ARGS((void));
+extern void dumpRelation ARGS((Relation));
+extern void dumpSortedStates ARGS((void));
+extern void dumpSortedRules ARGS((void));
+extern int debugTrim;
+
+#ifdef DEBUG
+#define debug(a,b)     if (a) b
+#else
+#define debug(a,b)
+#endif
+extern int debugTables;
+
+#define TABLE_INCR     8
+#define STATES_INCR    64
+
+#ifdef NDEBUG
+#define assert(c) ((void) 0)
+#else
+#define assert(c) ((void) ((c) || fatal(__FILE__,__LINE__)))
+#endif
+
+extern void doStart ARGS((char *));
+extern void exit ARGS((int));
+extern int fatal ARGS((char *, int));
+extern void yyerror ARGS((char *));
+extern void yyerror1 ARGS((char *));
diff --git a/utils/Burg/be.c b/utils/Burg/be.c
new file mode 100644 (file)
index 0000000..e7feab8
--- /dev/null
@@ -0,0 +1,1052 @@
+char rcsid_be[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+#include "fe.h"
+
+#define ERROR_VAL 0
+
+FILE *outfile;
+char *prefix = "burm";
+
+static void doKids ARGS((RuleAST));
+static void doLabel ARGS((Operator));
+static void doLayout ARGS((RuleAST));
+static void doMakeTable ARGS((Operator));
+static void doVector ARGS((RuleAST));
+static void layoutNts ARGS((PatternAST));
+static void makeIndex_Map ARGS((Dimension));
+static void makePvector ARGS((void));
+static void makeState ARGS((void));
+static void printPatternAST ARGS((PatternAST));
+static void printPatternAST_int ARGS((PatternAST));
+static void setVectors ARGS((PatternAST));
+static void trailing_zeroes ARGS((int));
+static int seminal ARGS((int from, int to));
+static void printRule ARGS((RuleAST, char *));
+
+static void
+doLabel(op) Operator op;
+{
+       fprintf(outfile, "\tcase %d:\n", op->num);
+
+       switch (op->arity) {
+       default:
+               assert(0);
+               break;
+       case 0:
+               fprintf(outfile, "\t\treturn %d;\n", op->table->transition[0]->num);
+               break;
+       case 1:
+               if (op->table->rules) {
+                       fprintf(outfile, "\t\treturn %s_%s_transition[l];\n", prefix, op->name);
+               } else {
+                       fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL);
+               }
+               break;
+       case 2:
+               if (op->table->rules) {
+                       fprintf(outfile, "\t\treturn %s_%s_transition[%s_%s_imap_1[l]][%s_%s_imap_2[r]];\n", prefix, op->name, prefix, op->name, prefix, op->name);
+               } else {
+                       fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL);
+               }
+               break;
+       }
+}
+
+int
+opsOfArity(arity) int arity;
+{
+       int c;
+       List l;
+
+       c = 0;
+       for (l = operators; l; l = l->next) {
+               Operator op = (Operator) l->x;
+               if (op->arity == arity) {
+                       fprintf(outfile, "\tcase %d:\n", op->num);
+                       c++;
+               }
+       }
+       return c;
+}
+
+static void
+trailing_zeroes(z) int z;
+{
+       int i;
+
+       for (i = 0; i < z; i++) {
+               fprintf(outfile, ", 0");
+       }
+}
+
+void
+makeLabel()
+{
+       int flag;
+
+       fprintf(outfile, "#ifdef __STDC__\n");
+       fprintf(outfile, "int %s_label(%s_NODEPTR_TYPE n) {\n", prefix, prefix);
+       fprintf(outfile, "#else\n");
+       fprintf(outfile, "int %s_label(n) %s_NODEPTR_TYPE n; {\n", prefix, prefix);
+       fprintf(outfile, "#endif\n");
+
+       fprintf(outfile, 
+       "\t%s_assert(n, %s_PANIC(\"NULL pointer passed to %s_label\\n\"));\n",
+                               prefix, prefix, prefix);
+       fprintf(outfile, "\tswitch (%s_OP_LABEL(n)) {\n", prefix);
+       fprintf(outfile, "\tdefault: %s_PANIC(\"Bad op %%d in %s_label\\n\", %s_OP_LABEL(n)); abort(); return 0;\n", 
+                       prefix, prefix, prefix);
+
+       flag = opsOfArity(0);
+       if (flag > 0) {
+               fprintf(outfile, "\t\treturn %s_STATE_LABEL(n) = %s_state(%s_OP_LABEL(n)",
+                                       prefix, prefix, prefix);
+               trailing_zeroes(max_arity);
+               fprintf(outfile, ");\n");
+       }
+       flag = opsOfArity(1);
+       if (flag > 0) {
+               fprintf(outfile, "\t\treturn %s_STATE_LABEL(n) = %s_state(%s_OP_LABEL(n), %s_label(%s_LEFT_CHILD(n))",
+                                       prefix, prefix, prefix, prefix, prefix);
+               trailing_zeroes(max_arity-1);
+               fprintf(outfile, ");\n");
+       }
+       flag = opsOfArity(2);
+       if (flag > 0) {
+               fprintf(outfile, "\t\treturn %s_STATE_LABEL(n) = %s_state(%s_OP_LABEL(n), %s_label(%s_LEFT_CHILD(n)), %s_label(%s_RIGHT_CHILD(n))",
+                                       prefix, prefix, prefix, prefix, prefix, prefix, prefix);
+               trailing_zeroes(max_arity-2);
+               fprintf(outfile, ");\n");
+
+       }
+       fprintf(outfile, "\t}\n");
+       fprintf(outfile, "}\n");
+}
+
+static void
+makeState()
+{
+       fprintf(outfile, "int %s_state(int op, int l, int r) {\n", prefix);
+       fprintf(outfile, 
+       "\t%s_assert(l >= 0 && l < %d, PANIC(\"Bad state %%d passed to %s_state\\n\", l));\n",
+                               prefix, globalMap->count, prefix);
+       fprintf(outfile, 
+       "\t%s_assert(r >= 0 && r < %d, PANIC(\"Bad state %%d passed to %s_state\\n\", r));\n",
+                               prefix, globalMap->count, prefix);
+       fprintf(outfile, "\tswitch (op) {\n");
+       fprintf(outfile, "\tdefault: %s_PANIC(\"Bad op %%d in %s_state\\n\", op); abort(); return 0;\n", prefix, prefix);
+
+       foreachList((ListFn) doLabel, operators);
+
+       fprintf(outfile, "\t}\n");
+       fprintf(outfile, "}\n");
+}
+
+static char cumBuf[4000];
+static int vecIndex;
+char vecBuf[4000];
+
+static void
+setVectors(ast) PatternAST ast;
+{
+       char old[4000];
+
+       switch (ast->sym->tag) {
+       default:
+               assert(0);
+               break;
+       case NONTERMINAL:
+               sprintf(old, "\t\tkids[%d] = %s;\n", vecIndex, vecBuf);
+               strcat(cumBuf, old);
+               vecIndex++;
+               return;
+       case OPERATOR:
+               switch (ast->sym->u.op->arity) {
+               default:
+                       assert(0);
+                       break;
+               case 0:
+                       return;
+               case 1:
+                       strcpy(old, vecBuf);
+                       sprintf(vecBuf, "%s_LEFT_CHILD(%s)", prefix, old);
+                       setVectors((PatternAST) ast->children->x);
+                       strcpy(vecBuf, old);
+                       return;
+               case 2:
+                       strcpy(old, vecBuf);
+                       sprintf(vecBuf, "%s_LEFT_CHILD(%s)", prefix, old);
+                       setVectors((PatternAST) ast->children->x);
+
+                       sprintf(vecBuf, "%s_RIGHT_CHILD(%s)", prefix, old);
+                       setVectors((PatternAST) ast->children->next->x);
+                       strcpy(vecBuf, old);
+                       return;
+               }
+               break;
+       }
+}
+
+#define MAX_VECTOR     10
+
+void
+makeRuleTable()
+{
+       int s,nt;
+
+       fprintf(outfile, "static short %s_RuleNo[%d][%d] = {\n", prefix, globalMap->count, last_user_nonterminal-1);
+       for (s = 0; s < globalMap->count; s++) {
+               Item_Set ts = globalMap->set[s];
+               if (s > 0) {
+                       fprintf(outfile, ",\n");
+               }
+               fprintf(outfile, "/* state %d */\n", s);
+               fprintf(outfile, "{");
+               for (nt = 1; nt < last_user_nonterminal; nt++) {
+                       if (nt > 1) {
+                               fprintf(outfile, ",");
+                               if (nt % 10 == 1) {
+                                       fprintf(outfile, "\t/* state %d; Nonterminals %d-%d */\n", s, nt-10, nt-1);
+                               }
+                       }
+                       if (ts->closed[nt].rule) {
+                               ts->closed[nt].rule->used = 1;
+                               fprintf(outfile, "%5d", ts->closed[nt].rule->erulenum);
+                       } else {
+                               fprintf(outfile, "%5d", ERROR_VAL);
+                       }
+               }
+               fprintf(outfile, "}");
+       }
+       fprintf(outfile, "};\n");
+}
+
+static void
+makeIndex_Map(d) Dimension d;
+{
+       int s;
+
+       for (s = 0; s < globalMap->count; s++) {
+               if (s > 0) {
+                       fprintf(outfile, ",");
+                       if (s % 10 == 0) {
+                               fprintf(outfile, "\t/* %d-%d */\n", s-10, s-1);
+                       }
+               }
+               fprintf(outfile, "%5d", d->map->set[d->index_map.class[s]->num]->num);
+       }
+       fprintf(outfile, "};\n");
+}
+
+static void
+doMakeTable(op) Operator op;
+{
+       int s;
+       int i,j;
+       Dimension d;
+
+       switch (op->arity) {
+       default:
+               assert(0);
+               break;
+       case 0:
+               return;
+       case 1:
+               if (!op->table->rules) {
+                       return;
+               }
+               d = op->table->dimen[0];
+               fprintf(outfile, "static short %s_%s_transition[%d] = {\n", prefix, op->name, globalMap->count);
+               for (s = 0; s < globalMap->count; s++) {
+                       if (s > 0) {
+                               fprintf(outfile, ", ");
+                               if (s % 10 == 0) {
+                                       fprintf(outfile, "\t/* %d-%d */\n", s-10, s-1);
+                               }
+                       }
+                       fprintf(outfile, "%5d", op->table->transition[d->map->set[d->index_map.class[s]->num]->num]->num);
+               }
+               fprintf(outfile, "};\n");
+               break;
+       case 2:
+               if (!op->table->rules) {
+                       return;
+               }
+               fprintf(outfile, "static short %s_%s_imap_1[%d] = {\n", prefix, op->name, globalMap->count);
+               makeIndex_Map(op->table->dimen[0]);
+               fprintf(outfile, "static short %s_%s_imap_2[%d] = {\n", prefix, op->name, globalMap->count);
+               makeIndex_Map(op->table->dimen[1]);
+
+               fprintf(outfile, "static short %s_%s_transition[%d][%d] = {", prefix, op->name,
+                                               op->table->dimen[0]->map->count,
+                                               op->table->dimen[1]->map->count);
+               for (i = 0; i < op->table->dimen[0]->map->count; i++) {
+                       if (i > 0) {
+                               fprintf(outfile, ",");
+                       }
+                       fprintf(outfile, "\n");
+                       fprintf(outfile, "{");
+                       for (j = 0; j < op->table->dimen[1]->map->count; j++) {
+                               Item_Set *ts = transLval(op->table, i, j);
+                               if (j > 0) {
+                                       fprintf(outfile, ",");
+                               }
+                               fprintf(outfile, "%5d", (*ts)->num);
+                       }
+                       fprintf(outfile, "}\t/* row %d */", i);
+               }
+               fprintf(outfile, "\n};\n");
+
+               break;
+       }
+}
+
+void
+makeTables()
+{
+       foreachList((ListFn) doMakeTable, operators);
+}
+
+RuleAST *pVector;
+
+void
+makeLHSmap()
+{
+       int i;
+
+       if (!pVector) {
+               makePvector();
+       }
+
+       fprintf(outfile, "short %s_lhs[] = {\n", prefix);
+       for (i = 0; i <= max_erule_num; i++) {
+               if (pVector[i]) {
+                       fprintf(outfile, "\t%s_%s_NT,\n", prefix, pVector[i]->lhs);
+               } else {
+                       fprintf(outfile, "\t0,\n");
+               }
+       }
+       fprintf(outfile, "};\n\n", prefix);
+}
+
+static int seminal(from, to)
+{
+       return allpairs[from][to].rule ? allpairs[from][to].rule->erulenum : 0;
+
+       /*
+       int tmp, last;
+       tmp = 0;
+       for (;;) {
+               last = tmp;
+               tmp = allpairs[to][from].rule ? allpairs[to][from].rule->erulenum : 0;
+               if (!tmp) {
+                       break;
+               }
+               assert(pVector[tmp]);
+               to = pVector[tmp]->rule->pat->children[0]->num;
+       }
+       return last;
+       */
+}
+
+void
+makeClosureArray()
+{
+       int i, j;
+
+       if (!pVector) {
+               makePvector();
+       }
+
+       fprintf(outfile, "short %s_closure[%d][%d] = {\n", prefix, last_user_nonterminal, last_user_nonterminal);
+       for (i = 0; i < last_user_nonterminal; i++) {
+               fprintf(outfile, "\t{");
+               for (j = 0; j < last_user_nonterminal; j++) {
+                       if (j > 0 && j%10 == 0) {
+                               fprintf(outfile, "\n\t ");
+                       }
+                       fprintf(outfile, " %4d,", seminal(i,j));
+               }
+               fprintf(outfile, "},\n");
+       }
+       fprintf(outfile, "};\n");
+}
+
+void
+makeCostVector(z,d) int z; DeltaCost d;
+{
+       fprintf(outfile, "\t{");
+#ifdef NOLEX
+       if (z) {
+               fprintf(outfile, "%5d", d);
+       } else {
+               fprintf(outfile, "%5d", 0);
+       }
+#else
+       {
+       int j;
+       for (j = 0; j < DELTAWIDTH; j++) {
+               if (j > 0) {
+                       fprintf(outfile, ",");
+               }
+               if (z) {
+                       fprintf(outfile, "%5d", d[j]);
+               } else {
+                       fprintf(outfile, "%5d", 0);
+               }
+       }
+       }
+#endif /* NOLEX */
+       fprintf(outfile, "}");
+}
+
+void
+makeCostArray()
+{
+       int i;
+
+       if (!pVector) {
+               makePvector();
+       }
+
+       fprintf(outfile, "short %s_cost[][%d] = {\n", prefix, DELTAWIDTH);
+       for (i = 0; i <= max_erule_num; i++) {
+               makeCostVector(pVector[i], pVector[i] ? pVector[i]->rule->delta : 0);
+               fprintf(outfile, ", /* ");
+               printRule(pVector[i], "(none)");
+               fprintf(outfile, " = %d */\n", i);
+       }
+       fprintf(outfile, "};\n");
+}
+
+void
+makeStateStringArray()
+{
+       int s;
+       int nt;
+       int states;
+       
+       states = globalMap->count;
+       fprintf(outfile, "\nconst char * %s_state_string[] = {\n", prefix);
+       fprintf(outfile, "\" not a state\", /* state 0 */\n");
+       for (s = 0; s < states-1; s++) {
+               fprintf(outfile, "\t\"");
+               printRepresentative(outfile, sortedStates[s]);
+               fprintf(outfile, "\", /* state #%d */\n", s+1);
+       }
+       fprintf(outfile, "};\n");
+}
+
+void
+makeDeltaCostArray()
+{
+       int s;
+       int nt;
+       int states;
+       
+       states = globalMap->count;
+       fprintf(outfile, "\nshort %s_delta_cost[%d][%d][%d] = {\n", prefix, states, last_user_nonterminal, DELTAWIDTH);
+       fprintf(outfile, "{{0}}, /* state 0 */\n");
+       for (s = 0; s < states-1; s++) {
+               fprintf(outfile, "{ /* state #%d: ", s+1);
+               printRepresentative(outfile, sortedStates[s]);
+               fprintf(outfile, " */\n", s+1);
+               fprintf(outfile, "\t{0},\n");
+               for (nt = 1; nt < last_user_nonterminal; nt++) {
+                       makeCostVector(1, sortedStates[s]->closed[nt].delta);
+                       fprintf(outfile, ", /* ");
+                       if (sortedStates[s]->closed[nt].rule) {
+                               int erulenum = sortedStates[s]->closed[nt].rule->erulenum;
+                               printRule(pVector[erulenum], "(none)");
+                               fprintf(outfile, " = %d */", erulenum);
+                       } else {
+                               fprintf(outfile, "(none) */");
+                       }
+                       fprintf(outfile, "\n");
+               }
+               fprintf(outfile, "},\n");
+       }
+       fprintf(outfile, "};\n");
+}
+
+static void
+printPatternAST_int(p) PatternAST p;
+{
+       List l;
+
+       if (p) {
+               switch (p->sym->tag) {
+               case NONTERMINAL:
+                       fprintf(outfile, "%5d,", -p->sym->u.nt->num);
+                       break;
+               case OPERATOR:
+                       fprintf(outfile, "%5d,", p->sym->u.op->num);
+                       break;
+               default:
+                       assert(0);
+               }
+               if (p->children) {
+                       for (l = p->children; l; l = l->next) {
+                               PatternAST pat = (PatternAST) l->x;
+                               printPatternAST_int(pat);
+                       }
+               }
+       }
+}
+
+static void
+printPatternAST(p) PatternAST p;
+{
+       List l;
+
+       if (p) {
+               fprintf(outfile, "%s", p->op);
+               if (p->children) {
+                       fprintf(outfile, "(");
+                       for (l = p->children; l; l = l->next) {
+                               PatternAST pat = (PatternAST) l->x;
+                               if (l != p->children) {
+                                       fprintf(outfile, ", ");
+                               }
+                               printPatternAST(pat);
+                       }
+                       fprintf(outfile, ")");
+               }
+       }
+}
+
+static void
+layoutNts(ast) PatternAST ast;
+{
+       char out[30];
+
+       switch (ast->sym->tag) {
+       default:
+               assert(0);
+               break;
+       case NONTERMINAL:
+               sprintf(out, "%d, ", ast->sym->u.nt->num);
+               strcat(cumBuf, out);
+               return;
+       case OPERATOR:
+               switch (ast->sym->u.op->arity) {
+               default:
+                       assert(0);
+                       break;
+               case 0:
+                       return;
+               case 1:
+                       layoutNts((PatternAST) ast->children->x);
+                       return;
+               case 2:
+                       layoutNts((PatternAST) ast->children->x);
+                       layoutNts((PatternAST) ast->children->next->x);
+                       return;
+               }
+               break;
+       }
+}
+
+static void
+doVector(ast) RuleAST ast;
+{
+       if (pVector[ast->rule->erulenum]) {
+               fprintf(stderr, "ERROR: non-unique external rule number: (%d)\n", ast->rule->erulenum);
+               exit(1);
+       }
+       pVector[ast->rule->erulenum] = ast;
+}
+
+static void
+makePvector()
+{
+       pVector = (RuleAST*) zalloc((max_erule_num+1) * sizeof(RuleAST));
+       foreachList((ListFn) doVector, ruleASTs);
+}
+
+static void
+doLayout(ast) RuleAST ast;
+{
+       sprintf(cumBuf, "{ ");
+       layoutNts(ast->pat);
+       strcat(cumBuf, "0 }");
+}
+
+void
+makeNts()
+{
+       int i;
+       int new;
+       StrTable nts;
+
+       nts = newStrTable();
+
+       if (!pVector) {
+               makePvector();
+       }
+
+       for (i = 0; i <= max_erule_num; i++) {
+               if (pVector[i]) {
+                       doLayout(pVector[i]);
+                       pVector[i]->nts = addString(nts, cumBuf, i, &new);
+                       if (new) {
+                               char ename[50];
+
+                               sprintf(ename, "%s_r%d_nts", prefix, i);
+                               pVector[i]->nts->ename = (char*) zalloc(strlen(ename)+1);
+                               strcpy(pVector[i]->nts->ename, ename);
+                               fprintf(outfile, "static short %s[] =", ename);
+                               fprintf(outfile, "%s;\n", cumBuf);
+                       }
+               }
+       }
+
+       fprintf(outfile, "short *%s_nts[] = {\n", prefix);
+       for (i = 0; i <= max_erule_num; i++) {
+               if (pVector[i]) {
+                       fprintf(outfile, "\t%s,\n", pVector[i]->nts->ename);
+               } else {
+                       fprintf(outfile, "\t0,\n");
+               }
+       }
+       fprintf(outfile, "};\n");
+}
+
+static void
+printRule(r,d) RuleAST r; char *d;
+{
+       if (r) {
+               fprintf(outfile, "%s: ", r->rule->lhs->name);
+               printPatternAST(r->pat);
+       } else {
+               fprintf(outfile, "%s", d);
+       }
+}
+
+void
+makeRuleDescArray()
+{
+       int i;
+
+       if (!pVector) {
+               makePvector();
+       }
+
+       if (last_user_nonterminal != max_nonterminal) {
+               /* not normal form */
+               fprintf(outfile, "short %s_rule_descriptor_0[] = { 0, 0 };\n", prefix);
+       } else {
+               fprintf(outfile, "short %s_rule_descriptor_0[] = { 0, 1 };\n", prefix);
+       }
+       for (i = 1; i <= max_erule_num; i++) {
+               if (pVector[i]) {
+                       Operator o;
+                       NonTerminal t;
+
+                       fprintf(outfile, "short %s_rule_descriptor_%d[] = {", prefix, i);
+                       fprintf(outfile, "%5d,", -pVector[i]->rule->lhs->num);
+                       printPatternAST_int(pVector[i]->pat);
+                       fprintf(outfile, " };\n");
+               }
+       }
+
+       fprintf(outfile, "/* %s_rule_descriptors[0][1] = 1 iff grammar is normal form. */\n", prefix);
+       fprintf(outfile, "short * %s_rule_descriptors[] = {\n", prefix);
+       fprintf(outfile, "\t%s_rule_descriptor_0,\n", prefix);
+       for (i = 1; i <= max_erule_num; i++) {
+               if (pVector[i]) {
+                       fprintf(outfile, "\t%s_rule_descriptor_%d,\n", prefix, i);
+               } else {
+                       fprintf(outfile, "\t%s_rule_descriptor_0,\n", prefix);
+               }
+       }
+       fprintf(outfile, "};\n");
+}
+
+
+void
+makeRuleDescArray2()
+{
+       int i;
+
+       if (!pVector) {
+               makePvector();
+       }
+
+       fprintf(outfile, "struct { int lhs, op, left, right; } %s_rule_struct[] = {\n", prefix);
+       if (last_user_nonterminal != max_nonterminal) {
+               /* not normal form */
+               fprintf(outfile, "\t{-1},");
+       } else {
+               fprintf(outfile, "\t{0},");
+       }
+       fprintf(outfile, " /* 0 if normal form, -1 if not normal form */\n");
+       for (i = 1; i <= max_erule_num; i++) {
+               fprintf(outfile, "\t");
+               if (pVector[i]) {
+                       Operator o;
+                       NonTerminal t;
+
+                       fprintf(outfile, "{");
+                       fprintf(outfile, "%5d, %5d, %5d, %5d",
+                               pVector[i]->rule->lhs->num,
+                               (o = pVector[i]->rule->pat->op) ? o->num : 0,
+                               (t = pVector[i]->rule->pat->children[0]) ? t->num : 0,
+                               (t = pVector[i]->rule->pat->children[1]) ? t->num : 0
+                               );
+                       fprintf(outfile, "} /* ");
+                       printRule(pVector[i], "0");
+                       fprintf(outfile, " = %d */", i);
+               } else {
+                       fprintf(outfile, "{0}");
+               }
+               fprintf(outfile, ",\n");
+       }
+       fprintf(outfile, "};\n");
+}
+
+void
+makeStringArray()
+{
+       int i;
+
+       if (!pVector) {
+               makePvector();
+       }
+
+       fprintf(outfile, "const char *%s_string[] = {\n", prefix);
+       for (i = 0; i <= max_erule_num; i++) {
+               fprintf(outfile, "\t");
+               if (pVector[i]) {
+                       fprintf(outfile, "\"");
+                       printRule(pVector[i], "0");
+                       fprintf(outfile, "\"");
+               } else {
+                       fprintf(outfile, "0");
+               }
+               fprintf(outfile, ",\n");
+       }
+       fprintf(outfile, "};\n");
+       fprintf(outfile, "int %s_max_rule = %d;\n", prefix, max_erule_num);
+       fprintf(outfile, "#define %s_Max_rule %d\n", prefix, max_erule_num);
+}
+
+void
+makeRule()
+{
+       fprintf(outfile, "int %s_rule(int state, int goalnt) {\n", prefix);
+       fprintf(outfile, 
+       "\t%s_assert(state >= 0 && state < %d, PANIC(\"Bad state %%d passed to %s_rule\\n\", state));\n",
+                               prefix, globalMap->count, prefix);
+       fprintf(outfile, 
+       "\t%s_assert(goalnt >= 1 && goalnt < %d, PANIC(\"Bad goalnt %%d passed to %s_rule\\n\", state));\n",
+                               prefix, max_nonterminal, prefix);
+       fprintf(outfile, "\treturn %s_RuleNo[state][goalnt-1];\n", prefix);
+       fprintf(outfile, "};\n");
+}
+
+static StrTable kids;
+
+static void
+doKids(ast) RuleAST ast;
+{
+       int new;
+
+       vecIndex = 0;
+       cumBuf[0] = 0;
+       strcpy(vecBuf, "p");
+       setVectors(ast->pat);
+
+       ast->kids = addString(kids, cumBuf, ast->rule->erulenum, &new);
+
+}
+
+void
+makeKids()
+{
+       List e;
+       IntList r;
+
+       kids = newStrTable();
+
+       fprintf(outfile, "#ifdef __STDC__\n");
+       fprintf(outfile, "%s_NODEPTR_TYPE * %s_kids(%s_NODEPTR_TYPE p, int rulenumber, %s_NODEPTR_TYPE *kids) {\n", prefix, prefix, prefix, prefix);
+       fprintf(outfile, "#else\n");
+       fprintf(outfile, "%s_NODEPTR_TYPE * %s_kids(p, rulenumber, kids) %s_NODEPTR_TYPE p; int rulenumber; %s_NODEPTR_TYPE *kids; {\n", prefix, prefix, prefix, prefix);
+       fprintf(outfile, "#endif\n");
+
+       fprintf(outfile, 
+       "\t%s_assert(p, %s_PANIC(\"NULL node pointer passed to %s_kids\\n\"));\n",
+                               prefix, prefix, prefix);
+       fprintf(outfile, 
+       "\t%s_assert(kids, %s_PANIC(\"NULL kids pointer passed to %s_kids\\n\"));\n",
+                               prefix, prefix, prefix);
+       fprintf(outfile, "\tswitch (rulenumber) {\n");
+       fprintf(outfile, "\tdefault:\n");
+       fprintf(outfile, "\t\t%s_PANIC(\"Unknown Rule %%d in %s_kids;\\n\", rulenumber);\n", prefix, prefix);
+       fprintf(outfile, "\t\tabort();\n");
+       fprintf(outfile, "\t\t/* NOTREACHED */\n");
+
+       foreachList((ListFn) doKids, ruleASTs);
+
+       for (e = kids->elems; e; e = e->next) {
+               StrTableElement el = (StrTableElement) e->x;
+               for (r = el->erulenos; r; r = r->next) {
+                       int i = r->x;
+                       fprintf(outfile, "\tcase %d:\n", i);
+               }
+               fprintf(outfile, "%s", el->str);
+               fprintf(outfile, "\t\tbreak;\n");
+       }
+       fprintf(outfile, "\t}\n");
+       fprintf(outfile, "\treturn kids;\n");
+       fprintf(outfile, "}\n");
+}
+
+void
+makeOpLabel()
+{
+       fprintf(outfile, "#ifdef __STDC__\n");
+       fprintf(outfile, "int %s_op_label(%s_NODEPTR_TYPE p) {\n", prefix, prefix);
+       fprintf(outfile, "#else\n");
+       fprintf(outfile, "int %s_op_label(p) %s_NODEPTR_TYPE p; {\n", prefix, prefix);
+       fprintf(outfile, "#endif\n");
+       fprintf(outfile, 
+       "\t%s_assert(p, %s_PANIC(\"NULL pointer passed to %s_op_label\\n\"));\n",
+                               prefix, prefix, prefix);
+       fprintf(outfile, "\treturn %s_OP_LABEL(p);\n", prefix);
+       fprintf(outfile, "}\n");
+}
+
+void
+makeStateLabel()
+{
+       fprintf(outfile, "#ifdef __STDC__\n");
+       fprintf(outfile, "int %s_state_label(%s_NODEPTR_TYPE p) {\n", prefix, prefix);
+       fprintf(outfile, "#else\n");
+       fprintf(outfile, "int %s_state_label(p) %s_NODEPTR_TYPE p; {\n", prefix, prefix);
+       fprintf(outfile, "#endif\n");
+
+       fprintf(outfile, 
+       "\t%s_assert(p, %s_PANIC(\"NULL pointer passed to %s_state_label\\n\"));\n",
+                               prefix, prefix, prefix);
+       fprintf(outfile, "\treturn %s_STATE_LABEL(p);\n", prefix);
+       fprintf(outfile, "}\n");
+}
+
+void
+makeChild()
+{
+       fprintf(outfile, "#ifdef __STDC__\n");
+       fprintf(outfile, "%s_NODEPTR_TYPE %s_child(%s_NODEPTR_TYPE p, int index) {\n", prefix, prefix, prefix);
+       fprintf(outfile, "#else\n");
+       fprintf(outfile, "%s_NODEPTR_TYPE %s_child(p, index) %s_NODEPTR_TYPE p; int index; {\n", prefix, prefix, prefix);
+       fprintf(outfile, "#endif\n");
+
+       fprintf(outfile, 
+       "\t%s_assert(p, %s_PANIC(\"NULL pointer passed to %s_child\\n\"));\n",
+                               prefix, prefix, prefix);
+       fprintf(outfile, "\tswitch (index) {\n");
+       fprintf(outfile, "\tcase 0:\n");
+       fprintf(outfile, "\t\treturn %s_LEFT_CHILD(p);\n", prefix);
+       fprintf(outfile, "\tcase 1:\n");
+       fprintf(outfile, "\t\treturn %s_RIGHT_CHILD(p);\n", prefix);
+       fprintf(outfile, "\t}\n");
+       fprintf(outfile, "\t%s_PANIC(\"Bad index %%d in %s_child;\\n\", index);\n", prefix, prefix);
+       fprintf(outfile, "\tabort();\n");
+       fprintf(outfile, "\treturn 0;\n");
+       fprintf(outfile, "}\n");
+}
+
+static Operator *opVector;
+static int maxOperator;
+
+void
+makeOperatorVector()
+{
+       List l;
+
+       maxOperator = 0;
+       for (l = operators; l; l = l->next) {
+               Operator op = (Operator) l->x;
+               if (op->num > maxOperator) {
+                       maxOperator = op->num;
+               }
+       }
+       opVector = (Operator*) zalloc((maxOperator+1) * sizeof(*opVector));
+       for (l = operators; l; l = l->next) {
+               Operator op = (Operator) l->x;
+               if (opVector[op->num]) {
+                       fprintf(stderr, "ERROR: Non-unique external symbol number (%d)\n", op->num);
+                       exit(1);
+               }
+               opVector[op->num] = op;
+       }
+}
+
+void
+makeOperators()
+{
+       int i;
+
+       if (!opVector) {
+               makeOperatorVector();
+       }
+       fprintf(outfile, "const char * %s_opname[] = {\n", prefix);
+       for (i = 0; i <= maxOperator; i++) {
+               if (i > 0) {
+                       fprintf(outfile, ", /* %d */\n", i-1);
+               }
+               if (opVector[i]) {
+                       fprintf(outfile, "\t\"%s\"", opVector[i]->name);
+               } else {
+                       fprintf(outfile, "\t0");
+               }
+       }
+       fprintf(outfile, "\n};\n");
+       fprintf(outfile, "char %s_arity[] = {\n", prefix);
+       for (i = 0; i <= maxOperator; i++) {
+               if (i > 0) {
+                       fprintf(outfile, ", /* %d */\n", i-1);
+               }
+               fprintf(outfile, "\t%d", opVector[i] ? opVector[i]->arity : -1);
+       }
+       fprintf(outfile, "\n};\n");
+       fprintf(outfile, "int %s_max_op = %d;\n", prefix, maxOperator);
+       fprintf(outfile, "int %s_max_state = %d;\n", prefix, globalMap->count-1);
+       fprintf(outfile, "#define %s_Max_state %d\n", prefix, globalMap->count-1);
+}
+
+void
+makeDebug()
+{
+       fprintf(outfile, "#ifdef DEBUG\n");
+       fprintf(outfile, "int %s_debug;\n", prefix);
+       fprintf(outfile, "#endif /* DEBUG */\n");
+}
+
+void
+makeSimple()
+{
+       makeRuleTable();
+       makeTables();
+       makeRule();
+       makeState();
+}
+
+void
+startOptional()
+{
+       fprintf(outfile, "#ifdef %s_STATE_LABEL\n", prefix);
+       fprintf(outfile, "#define %s_INCLUDE_EXTRA\n", prefix);
+       fprintf(outfile, "#else\n");
+       fprintf(outfile, "#ifdef STATE_LABEL\n");
+       fprintf(outfile, "#define %s_INCLUDE_EXTRA\n", prefix);
+       fprintf(outfile, "#define %s_STATE_LABEL \tSTATE_LABEL\n", prefix);
+       fprintf(outfile, "#define %s_NODEPTR_TYPE\tNODEPTR_TYPE\n", prefix);
+       fprintf(outfile, "#define %s_LEFT_CHILD  \tLEFT_CHILD\n", prefix);
+       fprintf(outfile, "#define %s_OP_LABEL    \tOP_LABEL\n", prefix);
+       fprintf(outfile, "#define %s_RIGHT_CHILD \tRIGHT_CHILD\n", prefix);
+       fprintf(outfile, "#endif /* STATE_LABEL */\n");
+       fprintf(outfile, "#endif /* %s_STATE_LABEL */\n\n", prefix);
+
+       fprintf(outfile, "#ifdef %s_INCLUDE_EXTRA\n\n", prefix);
+
+}
+
+void
+makeNonterminals()
+{
+       List l;
+
+       for (l = nonterminals; l; l = l->next) {
+               NonTerminal nt = (NonTerminal) l->x;
+               if (nt->num < last_user_nonterminal) {
+                       fprintf(outfile, "#define %s_%s_NT %d\n", prefix, nt->name, nt->num);
+               }
+       }
+       fprintf(outfile, "#define %s_NT %d\n", prefix, last_user_nonterminal-1);
+}
+
+void
+makeNonterminalArray()
+{
+       int i;
+       List l;
+       NonTerminal *nta;
+
+       nta = (NonTerminal *) zalloc(sizeof(*nta) * last_user_nonterminal);
+
+       for (l = nonterminals; l; l = l->next) {
+               NonTerminal nt = (NonTerminal) l->x;
+               if (nt->num < last_user_nonterminal) {
+                       nta[nt->num] = nt;
+               }
+       }
+
+       fprintf(outfile, "const char *%s_ntname[] = {\n", prefix);
+       fprintf(outfile, "\t\"Error: Nonterminals are > 0\",\n");
+       for (i = 1; i < last_user_nonterminal; i++) {
+               fprintf(outfile, "\t\"%s\",\n", nta[i]->name);
+       }
+       fprintf(outfile, "\t0\n");
+       fprintf(outfile, "};\n\n");
+
+       zfree(nta);
+}
+
+void
+endOptional()
+{
+       fprintf(outfile, "#endif /* %s_INCLUDE_EXTRA */\n", prefix);
+}
+
+void
+startBurm()
+{
+       fprintf(outfile, "#ifndef %s_PANIC\n", prefix);
+       fprintf(outfile, "#define %s_PANIC\tPANIC\n", prefix);
+       fprintf(outfile, "#endif /* %s_PANIC */\n", prefix);
+       fprintf(outfile, "#ifdef __STDC__\n");
+       fprintf(outfile, "extern void abort(void);\n");
+       fprintf(outfile, "#else\n");
+       fprintf(outfile, "extern void abort();\n");
+       fprintf(outfile, "#endif\n");
+       fprintf(outfile, "#ifdef NDEBUG\n");
+       fprintf(outfile, "#define %s_assert(x,y)\t;\n", prefix);
+       fprintf(outfile, "#else\n");
+       fprintf(outfile, "#define %s_assert(x,y)\tif(!(x)) {y; abort();}\n", prefix);
+       fprintf(outfile, "#endif\n");
+}
+
+void
+reportDiagnostics()
+{
+       List l;
+
+       for (l = operators; l; l = l->next) {
+               Operator op = (Operator) l->x;
+               if (!op->ref) {
+                       fprintf(stderr, "warning: Unreferenced Operator: %s\n", op->name);
+               }
+       }
+       for (l = rules; l; l = l->next) {
+               Rule r = (Rule) l->x;
+               if (!r->used && r->num < max_ruleAST) {
+                       fprintf(stderr, "warning: Unused Rule: #%d\n", r->erulenum);
+               }
+       }
+       if (!start->pmap) {
+               fprintf(stderr, "warning: Start Nonterminal (%s) does not appear on LHS.\n", start->name);
+       }
+
+       fprintf(stderr, "start symbol = \"%s\"\n", start->name);
+       fprintf(stderr, "# of states = %d\n", globalMap->count-1);
+       fprintf(stderr, "# of nonterminals = %d\n", max_nonterminal-1);
+       fprintf(stderr, "# of user nonterminals = %d\n", last_user_nonterminal-1);
+       fprintf(stderr, "# of rules = %d\n", max_rule);
+       fprintf(stderr, "# of user rules = %d\n", max_ruleAST);
+}
diff --git a/utils/Burg/burg.shar.gz b/utils/Burg/burg.shar.gz
new file mode 100644 (file)
index 0000000..173bbfd
Binary files /dev/null and b/utils/Burg/burg.shar.gz differ
diff --git a/utils/Burg/burs.c b/utils/Burg/burs.c
new file mode 100644 (file)
index 0000000..b4f8b83
--- /dev/null
@@ -0,0 +1,71 @@
+char rcsid_burs[] = "$Id$";
+
+#include "b.h"
+
+Item_Set errorState;
+
+static void doLeaf ARGS((Operator));
+
+static void
+doLeaf(leaf) Operator leaf;
+{
+       int new;
+       List pl;
+       Item_Set ts;
+       Item_Set tmp;
+
+       assert(leaf->arity == 0);
+
+       ts = newItem_Set(leaf->table->relevant);
+
+       for (pl = rules; pl; pl = pl->next) {
+               Rule p = (Rule) pl->x;
+               if (p->pat->op == leaf) {       
+                       if (!ts->virgin[p->lhs->num].rule || p->delta < ts->virgin[p->lhs->num].delta) {
+                               ts->virgin[p->lhs->num].rule = p;
+                               ASSIGNCOST(ts->virgin[p->lhs->num].delta, p->delta);
+                               ts->op = leaf;
+                       }
+               }
+       }
+       trim(ts);
+       zero(ts);
+       tmp = encode(globalMap, ts, &new);
+       if (new) {
+               closure(ts);
+               leaf->table->transition[0] = ts;
+               addQ(globalQ, ts);
+       } else {
+               leaf->table->transition[0] = tmp;
+               freeItem_Set(ts);
+       }
+}
+
+void
+build()
+{
+       int new;
+       List ol;
+       Item_Set ts;
+
+       globalQ = newQ();
+       globalMap = newMapping(GLOBAL_MAP_SIZE);
+
+       ts = newItem_Set(0);
+       errorState = encode(globalMap, ts, &new);
+       ts->closed = ts->virgin;
+       addQ(globalQ, ts);
+
+       foreachList((ListFn) doLeaf, leaves);
+
+       debug(debugTables, printf("---initial set of states ---\n"));
+       debug(debugTables, dumpMapping(globalMap));
+       debug(debugTables, foreachList((ListFn) dumpItem_Set, globalQ->head));
+       
+       for (ts = popQ(globalQ); ts; ts = popQ(globalQ)) {
+               for (ol = operators; ol; ol = ol->next) {
+                       Operator op = (Operator) ol->x;
+                       addToTable(op->table, ts);
+               }
+       }
+}
diff --git a/utils/Burg/closure.c b/utils/Burg/closure.c
new file mode 100644 (file)
index 0000000..70e1626
--- /dev/null
@@ -0,0 +1,95 @@
+char rcsid_closure[] = "$Id$";
+
+#include <stdio.h>
+#include "b.h"
+
+int prevent_divergence = 0;
+
+List chainrules;
+
+void
+findChainRules()
+{
+       List pl;
+
+       assert(!chainrules);
+
+       for (pl = rules; pl; pl = pl->next) {
+               Rule p = (Rule) pl->x;
+               if (!p->pat->op) {
+                       chainrules = newList(p, chainrules);
+               } else {
+                       p->pat->op->table->rules = newList(p, p->pat->op->table->rules);
+                       addRelevant(p->pat->op->table->relevant, p->lhs->num);
+               }
+       }
+}
+
+void
+zero(t) Item_Set t;
+{
+       int i;
+       DeltaCost base;
+       int exists;
+       int base_nt;
+
+       assert(!t->closed);
+
+       ZEROCOST(base);
+       exists = 0;
+       for (i = 0; i < max_nonterminal; i++) {
+               if (t->virgin[i].rule) {
+                       if (exists) {
+                               if (LESSCOST(t->virgin[i].delta, base)) {
+                                       ASSIGNCOST(base, t->virgin[i].delta);
+                                       base_nt = i;
+                               }
+                       } else {
+                               ASSIGNCOST(base, t->virgin[i].delta);
+                               exists = 1;
+                               base_nt = i;
+                       }
+               }
+       }
+       if (!exists) {
+               return;
+       }
+       for (i = 0; i < max_nonterminal; i++) {
+               if (t->virgin[i].rule) {
+                       MINUSCOST(t->virgin[i].delta, base);
+               }
+               NODIVERGE(t->virgin[i].delta, t, i, base_nt);
+       }
+}
+
+void
+closure(t) Item_Set t;
+{
+       int changes;
+       List pl;
+
+       assert(!t->closed);
+       t->closed = itemArrayCopy(t->virgin);
+
+       changes = 1;
+       while (changes) {
+               changes = 0;
+               for (pl = chainrules; pl; pl = pl->next) {
+                       Rule p = (Rule) pl->x;
+                       register Item *rhs_item = &t->closed[p->pat->children[0]->num];
+
+                       if (rhs_item->rule) {   /* rhs is active */
+                               DeltaCost dc;
+                               register Item *lhs_item = &t->closed[p->lhs->num];
+
+                               ASSIGNCOST(dc, rhs_item->delta);
+                               ADDCOST(dc, p->delta);
+                               if (LESSCOST(dc, lhs_item->delta) || !lhs_item->rule) {
+                                       ASSIGNCOST(lhs_item->delta, dc);
+                                       lhs_item->rule = p;
+                                       changes = 1;
+                               }
+                       }
+               }
+       }
+}
diff --git a/utils/Burg/delta.c b/utils/Burg/delta.c
new file mode 100644 (file)
index 0000000..d796549
--- /dev/null
@@ -0,0 +1,143 @@
+char rcsid_delta[] = "$Id$";
+
+#include <stdio.h>
+#include "b.h"
+#include "fe.h"
+
+int principleCost = 0;
+int lexical = 0;
+
+#ifndef NOLEX
+void
+ASSIGNCOST(l, r) DeltaPtr l; DeltaPtr r;
+{
+       int i;
+
+       if (lexical) {
+               for (i = 0; i < DELTAWIDTH; i++) {
+                       l[i] = r[i];
+               }
+       } else {
+                       l[0] = r[0];
+       }
+}
+
+void
+ADDCOST(l, r) DeltaPtr l; DeltaPtr r;
+{
+       int i;
+
+       if (lexical) {
+               for (i = 0; i < DELTAWIDTH; i++) {
+                       l[i] += r[i];
+               }
+       } else {
+               l[0] += r[0];
+       }
+}
+
+void
+MINUSCOST(l, r) DeltaPtr l; DeltaPtr r;
+{
+       int i;
+
+       if (lexical) {
+               for (i = 0; i < DELTAWIDTH; i++) {
+                       l[i] -= r[i];
+               }
+       } else {
+               l[0] -= r[0];
+       }
+}
+
+void
+ZEROCOST(x) DeltaPtr x;
+{
+       int i;
+
+       if (lexical) {
+               for (i = 0; i < DELTAWIDTH; i++) {
+                       x[i] = 0;
+               }
+       } else {
+               x[0] = 0;
+       }
+}
+
+int
+LESSCOST(l, r) DeltaPtr l; DeltaPtr r;
+{
+       int i;
+
+       if (lexical) {
+               for (i = 0; i < DELTAWIDTH; i++) {
+                       if (l[i] < r[i]) {
+                               return 1;
+                       } else if (l[i] > r[i]) {
+                               return 0;
+                       }
+               }
+               return 0;
+       } else {
+               return l[0] < r[0];
+       }
+}
+
+int
+EQUALCOST(l, r) DeltaPtr l; DeltaPtr r;
+{
+       int i;
+
+       if (lexical) {
+               for (i = 0; i < DELTAWIDTH; i++) {
+                       if (l[i] != r[i]) {
+                               return 0;
+                       }
+               }
+               return 1;
+       } else {
+               return l[0] == r[0];
+       }
+}
+#endif /* NOLEX */
+
+void
+CHECKDIVERGE(c, its, nt, base) DeltaPtr c; Item_Set its; int nt; int base;
+{
+       int i;
+
+       if (prevent_divergence <= 0) {
+               return;
+       }
+       if (lexical) {
+#ifndef NOLEX
+               for (i = 0; i < DELTAWIDTH; i++) {
+                       if (c[i] > prevent_divergence) {
+                               char ntname[100];
+                               char basename[100];
+                               nonTerminalName(ntname, nt);
+                               nonTerminalName(basename, base);
+                               fprintf(stderr, "ERROR:  The grammar appears to diverge\n");
+                               fprintf(stderr, "\tRelative Costs: %s(0), %s(%d)\n", basename, ntname, c[i]);
+                               fprintf(stderr, "\tOffending Operator: %s\n", its->op->name);
+                               fprintf(stderr, "\tOffending Tree: ");
+                               printRepresentative(stderr, its);
+                               fprintf(stderr, "\n");
+                               exit(1);
+                       }
+               }
+#endif /*NOLEX*/
+       } else if (PRINCIPLECOST(c) > prevent_divergence) {
+               char ntname[100];
+               char basename[100];
+               nonTerminalName(ntname, nt);
+               nonTerminalName(basename, base);
+               fprintf(stderr, "ERROR:  The grammar appears to diverge\n");
+               fprintf(stderr, "\tRelative Costs: %s(0), %s(%d)\n", basename, ntname, PRINCIPLECOST(c));
+               fprintf(stderr, "\tOffending Operator: %s\n", its->op->name);
+               fprintf(stderr, "\tOffending Tree: ");
+               printRepresentative(stderr, its);
+               fprintf(stderr, "\n");
+               exit(1);
+       }
+}
diff --git a/utils/Burg/fe.c b/utils/Burg/fe.c
new file mode 100644 (file)
index 0000000..36b373d
--- /dev/null
@@ -0,0 +1,403 @@
+char rcsid_fe[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+#include "fe.h"
+
+int grammarflag;
+
+static int arity;
+
+List   ruleASTs;
+List   grammarNts;
+
+static void doBinding ARGS((Binding));
+static void doDecl ARGS((Arity));
+static NonTerminal lookup ARGS((Pattern));
+static NonTerminal normalize ARGS((PatternAST, NonTerminal, Pattern *));
+static void doEnterNonTerm ARGS((RuleAST));
+static void doRule ARGS((RuleAST));
+static void doTable ARGS((Operator));
+
+static void
+doBinding(b) Binding b;
+{
+       int new;
+       Symbol s;
+
+       s = enter(b->name, &new);
+       if (!new) {
+               fprintf(stderr, "Non-unique name: %s\n", b->name);
+               exit(1);
+       }
+       s->tag = OPERATOR;
+       s->u.op = newOperator(b->name, b->opnum, arity);
+       if (arity == 0) {
+               leaves = newList(s->u.op, leaves);
+       }
+}
+
+static void
+doDecl(a) Arity a;
+{
+       if (!a) {
+               return;
+       }
+       arity = a->arity;
+       foreachList((ListFn) doBinding, a->bindings);
+}
+
+
+static List xpatterns;
+static int tcount;
+
+static NonTerminal
+lookup(p) Pattern p;
+{
+       char buf[10];
+       char *s;
+       List l;
+       NonTerminal n;
+       DeltaCost dummy;
+
+       for (l = xpatterns; l; l = l->next) {
+               Pattern x = (Pattern) l->x;
+               if (x->op == p->op 
+                               && x->children[0] == p->children[0]
+                               && x->children[1] == p->children[1]) {
+                       return x->normalizer;
+               }
+       }
+       sprintf(buf, "n%%%d", tcount++);
+       s = (char *) zalloc(strlen(buf)+1);
+       strcpy(s, buf);
+       n = newNonTerminal(s);
+       p->normalizer = n;
+       xpatterns = newList(p, xpatterns);
+       ZEROCOST(dummy);
+       (void) newRule(dummy, 0, n, p);
+       return n;
+}
+
+static NonTerminal
+normalize(ast, nt, patt) PatternAST ast; NonTerminal nt; Pattern *patt;
+{
+       Symbol s;
+       int new;
+       Pattern dummy;
+
+       s = enter(ast->op, &new);
+       ast->sym = s;
+       if (new) { 
+               fprintf(stderr, "Illegal use of %s --- undefined symbol\n", s->name);
+               exit(1);
+               return 0; /* shut up compilers */
+       } else if (s->tag == NONTERMINAL) {
+               if (ast->children) {
+                       fprintf(stderr, "Illegal use of %s, a non-terminal, as a terminal\n", s->name);
+                       exit(1);
+               }
+               *patt = newPattern(0);
+               (*patt)->children[0] = s->u.nt;
+               return s->u.nt;
+       } else {
+               s->u.op->ref = 1;
+               *patt = newPattern(s->u.op);
+               if (s->u.op->arity == -1) {
+                       if (!ast->children) {
+                               s->u.op->arity = 0;
+                               leaves = newList(s->u.op, leaves);
+                       } else if (!ast->children->next) {
+                               s->u.op->arity = 1;
+                       } else if (!ast->children->next->next) {
+                               s->u.op->arity = 2;
+                       } else {
+                               fprintf(stderr, "ERROR: Too many children (max = 2) for \"%s\"\n", s->name);
+                               exit(1);
+                       }
+                       if (s->u.op->arity > max_arity) {
+                               max_arity = s->u.op->arity;
+                       }
+               }
+               switch (s->u.op->arity) {
+               default:
+                       assert(0);
+                       break;
+               case 0:
+                       if (ast->children) {
+                               fprintf(stderr, "ERROR: Incorrect number of children for leaf operator, \"%s\"\n", s->name);
+                               exit(1);
+                       }
+                       break;
+               case 1:
+                       if (!ast->children || ast->children->next) {
+                               fprintf(stderr, "ERROR: Incorrect number of children for unary operator, \"%s\"\n", s->name);
+                               exit(1);
+                       }
+                       (*patt)->children[0] = normalize((PatternAST) ast->children->x, 0, &dummy);
+                       break;
+               case 2:
+                       if (!ast->children || !ast->children->next) {
+                               fprintf(stderr, "ERROR: Incorrect number of children for binary operator, \"%s\"\n", s->name);
+                               exit(1);
+                       }
+                       (*patt)->children[0] = normalize((PatternAST) ast->children->x, 0, &dummy);
+                       (*patt)->children[1] = normalize((PatternAST) ast->children->next->x, 0, &dummy);
+                       break;
+               }
+               if (nt) {
+                       (*patt)->normalizer = nt;
+                       return nt;
+               } else {
+                       return lookup(*patt);
+               }
+       }
+}
+
+static void
+doEnterNonTerm(ast) RuleAST ast;
+{
+       int new;
+       Symbol s;
+       DeltaCost delta;
+       int i;
+       IntList p;
+
+
+       s = enter(ast->lhs, &new);
+       if (new) {
+               s->u.nt = newNonTerminal(s->name);
+               s->tag = NONTERMINAL;
+       } else {
+               if (s->tag != NONTERMINAL) {
+                       fprintf(stderr, "Illegal use of %s as a non-terminal\n", s->name);
+                       exit(1);
+               }
+       }
+       ZEROCOST(delta);
+       for (p = ast->cost, i = 0; p; p = p->next, i++) {
+               int x = p->x;
+#ifndef NOLEX
+               if (lexical) {
+                       if (i < DELTAWIDTH) {
+                               delta[i] = x;
+                       }
+               } else 
+#endif /* NOLEX */
+               {
+                       if (i == principleCost) {
+                               PRINCIPLECOST(delta) = x;
+                       }
+               }
+       }
+       ast->rule = newRule(delta, ast->erulenum, s->u.nt, 0);
+}
+
+static void
+doRule(ast) RuleAST ast;
+{
+       Pattern pat;
+
+       (void) normalize(ast->pat, ast->rule->lhs, &pat);
+       ast->rule->pat = pat;
+}
+
+static void
+doTable(op) Operator op;
+{
+       op->table = newTable(op);
+}
+
+void 
+doSpec(decls, rules) List decls; List rules;
+{
+       foreachList((ListFn) doDecl, decls);
+       debug(debugTables, foreachList((ListFn) dumpOperator_l, operators));
+
+       ruleASTs = rules;
+       reveachList((ListFn) doEnterNonTerm, rules);
+
+       last_user_nonterminal = max_nonterminal;
+
+       reveachList((ListFn) doRule, rules);
+       debug(debugTables, foreachList((ListFn) dumpRule, rules));
+
+       foreachList((ListFn) doTable, operators);
+}
+
+void
+doStart(name) char *name;
+{
+       Symbol s;
+       int new;
+
+       if (start) {
+               yyerror1("Redeclaration of start symbol to be ");
+               fprintf(stderr, "\"%s\"\n", name);
+               exit(1);
+       }
+       s = enter(name, &new);
+       if (new) {
+               s->u.nt = newNonTerminal(s->name);
+               s->tag = NONTERMINAL;
+       } else {
+               if (s->tag != NONTERMINAL) {
+                       fprintf(stderr, "Illegal use of %s as a non-terminal\n", s->name);
+                       exit(1);
+               }
+       }
+}
+
+void
+doGrammarNts()
+{
+       List l;
+       int new;
+
+       for (l = grammarNts; l; l = l->next) {
+               char *n = (char*) l->x;
+               Symbol s;
+
+               s = enter(n, &new);
+               if (new) {
+                       fprintf(stderr, "ERROR: %%gram, unused non-terminal: \"%s\"\n", n);
+                       exit(1);
+               }
+               if (s->tag != NONTERMINAL) {
+                       fprintf(stderr, "ERROR: %%gram, Not a non-terminal: \"%s\"\n", n);
+                       exit(1);
+               }
+               l->x = s;
+       }
+}
+
+void
+doGram(nts) List nts;
+{
+       if (grammarNts) {
+               yyerror1("Redeclaration of %%gram\n");
+               exit(1);
+       }
+       grammarNts = nts;
+}
+
+Arity 
+newArity(ar, b) int ar; List b;
+{
+       Arity a = (Arity) zalloc(sizeof(struct arity));
+       a->arity = ar;
+       a->bindings = b;
+       return a;
+}
+
+Binding 
+newBinding(name, opnum) char *name; int opnum;
+{
+       Binding b = (Binding) zalloc(sizeof(struct binding));
+       if (opnum == 0) {
+               yyerror1("ERROR: Non-positive external symbol number, ");
+               fprintf(stderr, "%d", opnum);
+               exit(1);
+       }
+       b->name = name;
+       b->opnum = opnum;
+       return b;
+}
+
+PatternAST
+newPatternAST(op, children) char *op; List children;
+{
+       PatternAST p = (PatternAST) zalloc(sizeof(struct patternAST));
+       p->op = op;
+       p->children = children;
+       return p;
+}
+
+int max_ruleAST;
+
+RuleAST
+newRuleAST(lhs, pat, erulenum, cost) char *lhs; PatternAST pat; int erulenum; IntList cost;
+{
+       RuleAST p = (RuleAST) zalloc(sizeof(struct ruleAST));
+       p->lhs = lhs;
+       p->pat = pat;
+       if (erulenum <= 0) {
+               yyerror1("External Rulenumber ");
+               fprintf(stderr, "(%d) <= 0\n", erulenum);
+               exit(1);
+       }
+       p->erulenum = erulenum;
+       p->cost = cost;
+       max_ruleAST++;
+       return p;
+}
+
+void
+dumpBinding(b) Binding b;
+{
+       printf("%s=%d ", b->name, b->opnum);
+}
+
+void
+dumpArity(a) Arity a;
+{
+       List l;
+
+       printf("Arity(%d) ", a->arity);
+       for (l = a->bindings; l; l = l->next) {
+               Binding b = (Binding) l->x;
+               dumpBinding(b);
+       }
+       printf("\n");
+}
+
+void
+dumpPatternAST(p) PatternAST p;
+{
+       List l;
+
+       printf("%s", p->op);
+       if (p->children) {
+               printf("(");
+               for (l = p->children; l; l = l->next) {
+                       PatternAST past = (PatternAST) l->x;
+                       dumpPatternAST(past);
+                       if (l->next) {
+                               printf(", ");
+                       }
+               }
+               printf(")");
+       }
+}
+
+void
+dumpRuleAST(p) RuleAST p;
+{
+       printf("%s : ", p->lhs);
+       dumpPatternAST(p->pat);
+       printf(" = %d (%ld)\n", p->erulenum, (long) p->cost);
+}
+
+void
+dumpDecls(decls) List decls;
+{
+       List l;
+
+       for (l = decls; l; l = l->next) {
+               Arity a = (Arity) l->x;
+               dumpArity(a);
+       }
+}
+
+void
+dumpRules(rules) List rules;
+{
+       List l;
+
+       for (l = rules; l; l = l->next) {
+               RuleAST p = (RuleAST) l->x;
+               dumpRuleAST(p);
+       }
+}
+
diff --git a/utils/Burg/fe.h b/utils/Burg/fe.h
new file mode 100644 (file)
index 0000000..5cef79b
--- /dev/null
@@ -0,0 +1,127 @@
+/* $Id$ */
+
+struct binding {
+       char    *name;
+       int     opnum;
+};
+typedef struct binding *Binding;
+
+struct arity {
+       int     arity;
+       List    bindings;
+};
+typedef struct arity   *Arity;
+
+struct patternAST {
+       struct symbol *sym;
+       char    *op;
+       List    children;
+};
+typedef struct patternAST      *PatternAST;
+
+struct ruleAST {
+       char                    *lhs;
+       PatternAST              pat;
+       int                     erulenum;
+       IntList                 cost;
+       struct rule             *rule;
+       struct strTableElement  *kids;
+       struct strTableElement  *nts;
+};
+typedef struct ruleAST *RuleAST;
+
+typedef enum {
+       UNKNOWN,
+       OPERATOR,
+       NONTERMINAL
+} TagType;
+
+struct symbol {
+       char    *name;
+       TagType tag;
+       union {
+               NonTerminal     nt;
+               Operator        op;
+       } u;
+};
+typedef struct symbol  *Symbol;
+
+struct strTableElement {
+       char *str;
+       IntList erulenos;
+       char *ename;
+};
+typedef struct strTableElement *StrTableElement;
+
+struct strTable {
+       List elems;
+};
+typedef struct strTable        *StrTable;
+
+extern StrTable newStrTable ARGS((void));
+extern StrTableElement addString ARGS((StrTable, char *, int, int *));
+
+extern void doSpec ARGS((List, List));
+extern Arity newArity ARGS((int, List));
+extern Binding newBinding ARGS((char *, int));
+extern PatternAST newPatternAST ARGS((char *, List));
+extern RuleAST newRuleAST ARGS((char *, PatternAST, int, IntList));
+extern Symbol enter ARGS((char *, int *));
+extern Symbol newSymbol ARGS((char *));
+
+extern void makeDebug ARGS((void));
+extern void makeSimple ARGS((void));
+extern void makePlanks ARGS((void));
+extern void makeOpLabel ARGS((void));
+extern void makeChild ARGS((void));
+extern void makeOperators ARGS((void));
+extern void makeLabel ARGS((void));
+extern void makeString ARGS((void));
+extern void makeString ARGS((void));
+extern void makeReduce ARGS((void));
+extern void makeRuleTable ARGS((void));
+extern void makeTables ARGS((void));
+extern void makeTreecost ARGS((void));
+extern void makePrint ARGS((void));
+extern void makeRule ARGS((void));
+extern void makeNts ARGS((void));
+extern void makeKids ARGS((void));
+extern void startBurm ARGS((void));
+extern void startOptional ARGS((void));
+extern void makePlankLabel ARGS((void));
+extern void makeStateLabel ARGS((void));
+extern void makeStringArray ARGS((void));
+extern void makeNonterminalArray ARGS((void));
+extern void makeCostArray ARGS((void));
+extern void makeLHSmap ARGS((void));
+extern void makeClosureArray ARGS((void));
+extern void makeOperatorVector ARGS((void));
+extern void endOptional ARGS((void));
+extern void reportDiagnostics ARGS((void));
+extern void makeNonterminals ARGS((void));
+extern int opsOfArity ARGS((int));
+
+extern void yypurge ARGS((void));
+extern void yyfinished ARGS((void));
+
+extern void printRepresentative ARGS((FILE *, Item_Set));
+
+extern void dumpRules ARGS((List));
+extern void dumpDecls ARGS((List));
+extern void dumpRuleAST ARGS((RuleAST));
+extern void dumpPatternAST ARGS((PatternAST));
+extern void dumpArity ARGS((Arity));
+extern void dumpBinding ARGS((Binding));
+extern void dumpStrTable ARGS((StrTable));
+
+extern int yylex ARGS((void));
+extern int yyparse ARGS((void));
+
+extern int     max_ruleAST;
+extern List    ruleASTs;
+
+extern FILE    *outfile;
+extern char    *prefix;
+extern int     trimflag;
+extern int     speedflag;
+extern int     grammarflag;
diff --git a/utils/Burg/gram.y b/utils/Burg/gram.y
new file mode 100644 (file)
index 0000000..f6f16fa
--- /dev/null
@@ -0,0 +1,90 @@
+%{
+char rcsid_gram[] = "$Id$";
+
+#include <stdio.h>
+#include "b.h"
+#include "fe.h"
+%}
+
+%union {
+       int y_int;
+       char *y_string;
+       Arity y_arity;
+       Binding y_binding;
+       PatternAST y_patternAST;
+       RuleAST y_ruleAST;
+       List y_list;
+       IntList y_intlist;
+}
+
+%start full
+
+%term ERROR
+%term K_TERM
+%term K_GRAM
+%term K_START
+%term K_PPERCENT
+%term INT
+%term ID
+
+%token <y_string> ID
+%token <y_int> INT
+
+%type <y_arity> decl
+%type <y_binding> binding
+%type <y_intlist> cost costtail
+%type <y_ruleAST> rule
+%type <y_patternAST> pattern
+%type <y_list> decls rules bindinglist grammarlist
+%%
+
+
+full   : spec
+       | spec K_PPERCENT
+               { yyfinished(); }
+       ;
+
+spec   : decls K_PPERCENT rules
+               = { doSpec($1, $3); }
+       ;
+
+decls  : /* lambda */  = { $$ = 0; }
+       | decls decl    = { $$ = newList($2, $1); }
+       ;
+
+decl   : K_TERM bindinglist    = { $$ = newArity(-1, $2); }
+       | K_GRAM grammarlist    = { $$ = 0; doGram($2); }
+       | K_START ID            = { $$ = 0; doStart($2); }      /* kludge */
+       ;
+
+grammarlist    : /* lambda */          = { $$ = 0; }
+               | grammarlist ID        = { $$ = newList($2, $1); }
+               ;
+
+bindinglist    : /* lambda */          = { $$ = 0; }
+               | bindinglist binding   = { $$ = newList($2, $1); }
+               ;
+
+binding        : ID '=' INT    = { $$ = newBinding($1, $3); }
+       ;
+
+rules  : /* lambda */  = { $$ = 0; }
+       | rules rule    = { $$ = newList($2, $1); }
+       ;
+
+rule   : ID ':' pattern '=' INT cost ';'       = { $$ = newRuleAST($1, $3, $5, $6); }
+               ;
+
+pattern        : ID                                    = { $$ = newPatternAST($1, 0); }
+       | ID '(' pattern ')'                    = { $$ = newPatternAST($1, newList($3,0)); }
+       | ID '(' pattern ',' pattern ')'        = { $$ = newPatternAST($1, newList($3, newList($5, 0))); }
+       ;
+
+cost   : /* lambda */          = { $$ = 0; }
+       | '(' INT costtail ')'  = { $$ = newIntList($2, $3); }
+       ;
+
+costtail       : /* lambda */          = { $$ = 0; }
+               | ',' INT costtail      = { $$ = newIntList($2, $3); }
+               | INT costtail          = { $$ = newIntList($1, $2); }
+               ;
diff --git a/utils/Burg/item.c b/utils/Burg/item.c
new file mode 100644 (file)
index 0000000..4a9f4a3
--- /dev/null
@@ -0,0 +1,133 @@
+char rcsid_item[] = "$Id$";
+
+#include "b.h"
+#include <stdio.h>
+#include <string.h>
+#include "fe.h"
+
+static Item_Set fptr;
+
+ItemArray
+newItemArray()
+{
+       ItemArray ia;
+       ia = (ItemArray) zalloc(max_nonterminal *sizeof(*ia));
+       return ia;
+}
+
+ItemArray
+itemArrayCopy(src) ItemArray src;
+{
+       ItemArray dst;
+
+       dst = newItemArray();
+       memcpy(dst, src, max_nonterminal * sizeof(*dst));
+       return dst;
+}
+
+Item_Set
+newItem_Set(relevant) Relevant relevant;
+{
+       Item_Set ts;
+       
+       if (fptr) {
+               ts = fptr;
+               fptr = 0;
+               memset(ts->virgin, 0, max_nonterminal * sizeof(struct item));
+               if (ts->closed) {
+                       zfree(ts->closed);
+                       ts->closed = 0;
+               }
+               ts->num = 0;
+               ts->op = 0;
+       } else {
+               ts = (Item_Set) zalloc(sizeof(struct item_set));
+               ts->virgin = newItemArray();
+       }
+       ts->relevant = relevant;
+       return ts;
+}
+
+void
+freeItem_Set(ts) Item_Set ts;
+{
+       assert(!fptr);
+       fptr = ts;
+}
+
+int
+equivSet(a, b) Item_Set a; Item_Set b;
+{
+       register Relevant r;
+       register int nt;
+       register Item *aa = a->virgin;
+       register Item *ba = b->virgin;
+
+       /*
+       return !bcmp(a->virgin, b->virgin, max_nonterminal * sizeof(Item));
+       */
+
+       r = a->relevant ? a->relevant : b->relevant;
+       assert(r);
+
+       if (a->op && b->op && a->op != b->op) {
+               return 0;
+       }
+       for (; (nt = *r) != 0; r++) {
+               if (aa[nt].rule != ba[nt].rule || !EQUALCOST(aa[nt].delta, ba[nt].delta)) {
+                       return 0;
+               }
+       }
+       return 1;
+}
+
+void
+printRepresentative(f, s) FILE *f; Item_Set s;
+{
+       if (!s) {
+               return;
+       }
+       fprintf(f, "%s", s->op->name);
+       switch (s->op->arity) {
+       case 1:
+               fprintf(f, "(");
+               printRepresentative(f, s->kids[0]);
+               fprintf(f, ")");
+               break;
+       case 2:
+               fprintf(f, "(");
+               printRepresentative(f, s->kids[0]);
+               fprintf(f, ", ");
+               printRepresentative(f, s->kids[1]);
+               fprintf(f, ")");
+               break;
+       }
+}
+
+void
+dumpItem(t) Item *t;
+{
+       printf("[%s #%d]", t->rule->lhs->name, t->rule->num);
+       dumpCost(t->delta);
+}
+
+void
+dumpItem_Set(ts) Item_Set ts;
+{
+       int i;
+
+       printf("Item_Set #%d: [", ts->num);
+       for (i = 1; i < max_nonterminal; i++) {
+               if (ts->virgin[i].rule) {
+                       printf(" %d", i);
+                       dumpCost(ts->virgin[i].delta);
+               }
+       }
+       printf(" ]\n");
+}
+
+void
+dumpCost(dc) DeltaCost dc;
+{
+       printf("(%ld)", (long) dc);
+}
diff --git a/utils/Burg/lex.c b/utils/Burg/lex.c
new file mode 100644 (file)
index 0000000..3d6c5af
--- /dev/null
@@ -0,0 +1,260 @@
+char rcsid_lex[] = "$Id$";
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+#include "fe.h"
+#include "y.tab.h"
+
+static char buf[BUFSIZ];
+
+static int yyline = 1;
+
+typedef int (*ReadFn) ARGS((void));
+
+static char *StrCopy ARGS((char *));
+static int code_get ARGS((void));
+static int simple_get ARGS((void));
+static void ReadCharString ARGS((ReadFn, int));
+static void ReadCodeBlock ARGS((void));
+static void ReadOldComment ARGS((ReadFn));
+
+static char *
+StrCopy(s) char *s;
+{
+       char *t = (char *)zalloc(strlen(s) + 1);
+       strcpy(t,s);
+       return t;
+}
+
+static int
+simple_get()
+{
+       int ch;
+       if ((ch = getchar()) == '\n') {
+               yyline++;
+       }
+       return ch;
+}
+
+static int
+code_get()
+{
+       int ch;
+       if ((ch = getchar()) == '\n') {
+               yyline++;
+       }
+       if (ch != EOF) {
+               fputc(ch, outfile);
+       }
+       return ch;
+}
+
+void
+yypurge()
+{
+       while (code_get() != EOF) ;
+}
+
+
+static void
+ReadCharString(rdfn, which) ReadFn rdfn; int which;
+{
+       int ch;
+       int backslash = 0;
+       int firstline = yyline;
+
+       while ((ch = rdfn()) != EOF) {
+               if (ch == which && !backslash) {
+                       return;
+               }
+               if (ch == '\\' && !backslash) {
+                       backslash = 1;
+               } else {
+                       backslash = 0;
+               }
+       }
+       yyerror1("Unexpected EOF in string on line ");
+       fprintf(stderr, "%d\n", firstline);
+       exit(1);
+}
+
+static void
+ReadOldComment(rdfn) ReadFn rdfn;
+{
+       /* will not work for comments delimiter in string */
+
+       int ch;
+       int starred = 0;
+       int firstline = yyline;
+
+       while ((ch = rdfn()) != EOF) {
+               if (ch == '*') {
+                       starred = 1;
+               } else if (ch == '/' && starred) {
+                       return;
+               } else {
+                       starred = 0;
+               }
+       }
+       yyerror1("Unexpected EOF in comment on line ");
+       fprintf(stderr, "%d\n", firstline);
+       exit(1);
+}
+
+static void
+ReadCodeBlock()
+{
+       int ch;
+       int firstline = yyline;
+
+       while ((ch = getchar()) != EOF) {
+               if (ch == '%') {
+                       ch = getchar();
+                       if (ch != '}') {
+                               yyerror("bad %%");
+                       }
+                       return;
+               }
+               fputc(ch, outfile);
+               if (ch == '\n') {
+                       yyline++;
+               }
+               if (ch == '"' || ch == '\'') {
+                       ReadCharString(code_get, ch);
+               } else if (ch == '/') {
+                       ch = getchar();
+                       if (ch == '*') {
+                               fputc(ch, outfile);
+                               ReadOldComment(code_get);
+                               continue;
+                       } else {
+                               ungetc(ch, stdin);
+                       }
+               }
+       }
+       yyerror1("Unclosed block of C code started on line ");
+       fprintf(stderr, "%d\n", firstline);
+       exit(1);
+}
+
+static int done;
+void
+yyfinished()
+{
+       done = 1;
+}
+
+int
+yylex()
+{
+       int ch;
+       char *ptr = buf;
+
+       if (done) return 0;
+       while ((ch = getchar()) != EOF) {
+               switch (ch) {
+               case ' ':
+               case '\f':
+               case '\t':
+                       continue;
+               case '\n':
+                       yyline++;
+                       continue;
+               case '(':
+               case ')':
+               case ',':
+               case ':':
+               case ';':
+               case '=':
+                       return(ch);
+               case '/':
+                       ch = getchar();
+                       if (ch == '*') {
+                               ReadOldComment(simple_get);
+                               continue;
+                       } else {
+                               ungetc(ch, stdin);
+                               yyerror("illegal char /");
+                               continue;
+                       }
+               case '%':
+                       ch = getchar();
+                       switch (ch) {
+                       case '%':
+                               return (K_PPERCENT);
+                       case '{':
+                               ReadCodeBlock();
+                               continue;
+                       case 's':
+                       case 'g':
+                       case 't':
+                               do {
+                                       if (ptr >= &buf[BUFSIZ]) {
+                                               yyerror("ID too long");
+                                               return(ERROR);
+                                       } else {
+                                               *ptr++ = ch;
+                                       }
+                                       ch = getchar();
+                               } while (isalpha(ch) || isdigit(ch) || ch == '_');
+                               ungetc(ch, stdin);
+                               *ptr = '\0';
+                               if (!strcmp(buf, "term")) return K_TERM;
+                               if (!strcmp(buf, "start")) return K_START;
+                               if (!strcmp(buf, "gram")) return K_GRAM;
+                               yyerror("illegal character after %%");
+                               continue;
+                       default:
+                               yyerror("illegal character after %%");
+                               continue;
+                       }
+               default:
+                       if (isalpha(ch) ) {
+                               do {
+                                       if (ptr >= &buf[BUFSIZ]) {
+                                               yyerror("ID too long");
+                                               return(ERROR);
+                                       } else {
+                                               *ptr++ = ch;
+                                       }
+                                       ch = getchar();
+                               } while (isalpha(ch) || isdigit(ch) || ch == '_');
+                               ungetc(ch, stdin);
+                               *ptr = '\0';
+                               yylval.y_string = StrCopy(buf);
+                               return(ID);
+                       } 
+                       if (isdigit(ch)) {
+                               int val=0;
+                               do {
+                                       val *= 10;
+                                       val += (ch - '0');
+                                       ch = getchar();
+                               } while (isdigit(ch));
+                               ungetc(ch, stdin);
+                               yylval.y_int = val;
+                               return(INT);
+                       }
+                       yyerror1("illegal char ");
+                       fprintf(stderr, "(\\%03o)\n", ch);
+                       exit(1);
+               }
+       }
+       return(0);
+}
+
+void
+yyerror1(str) char *str;
+{
+       fprintf(stderr, "line %d: %s", yyline, str);
+}
+
+void
+yyerror(str) char *str;
+{
+       yyerror1(str);
+       fprintf(stderr, "\n");
+       exit(1);
+}
diff --git a/utils/Burg/list.c b/utils/Burg/list.c
new file mode 100644 (file)
index 0000000..d3eefa2
--- /dev/null
@@ -0,0 +1,75 @@
+char rcsid_list[] = "$Id$";
+
+#include "b.h"
+
+IntList
+newIntList(x, next) int x; IntList next;
+{
+       IntList l;
+
+       l = (IntList) zalloc(sizeof(*l));
+       assert(l);
+       l->x = x;
+       l->next = next;
+
+       return l;
+}
+
+List
+newList(x, next) void *x; List next;
+{
+       List l;
+
+       l = (List) zalloc(sizeof(*l));
+       assert(l);
+       l->x = x;
+       l->next = next;
+
+       return l;
+}
+
+List
+appendList(x, l) void *x; List l;
+{
+       List last;
+       List p;
+
+       last = 0;
+       for (p = l; p; p = p->next) {
+               last = p;
+       }
+       if (last) {
+               last->next = newList(x, 0);
+               return l;
+       } else {
+               return newList(x, 0);
+       }
+}
+
+void
+foreachList(f, l) ListFn f; List l;
+{
+       for (; l; l = l->next) {
+               (*f)(l->x);
+       }
+}
+
+void
+reveachList(f, l) ListFn f; List l;
+{
+       if (l) {
+               reveachList(f, l->next);
+               (*f)(l->x);
+       }
+}
+
+int
+length(l) List l;
+{
+       int c = 0;
+
+       for(; l; l = l->next) {
+               c++;
+       }
+       return c;
+}
diff --git a/utils/Burg/main.c b/utils/Burg/main.c
new file mode 100644 (file)
index 0000000..5c13698
--- /dev/null
@@ -0,0 +1,182 @@
+char rcsid_main[] = "$Id$";
+
+#include <math.h>
+#include <stdio.h>
+#include "b.h"
+#include "fe.h"
+
+int debugTables = 0;
+static int simpleTables = 0;
+static int internals = 0;
+static int diagnostics = 0;
+
+static char *inFileName;
+static char *outFileName;
+
+static char version[] = "BURG, Version 1.0";
+
+extern void main ARGS((int argc, char **argv));
+
+void
+main(argc, argv) int argc; char **argv;
+{
+       int i;
+       extern int atoi ARGS((char *));
+
+       for (i = 1; argv[i]; i++) {
+               char **needStr = 0;
+               int *needInt = 0;
+
+               if (argv[i][0] == '-') {
+                       switch (argv[i][1]) {
+                       case 'V':
+                               fprintf(stderr, "%s\n", version);
+                               break;
+                       case 'p':
+                               needStr = &prefix;
+                               break;
+                       case 'o':
+                               needStr = &outFileName;
+                               break;
+                       case 'I':
+                               internals = 1;
+                               break;
+                       case 'T':
+                               simpleTables = 1;
+                               break;
+                       case '=':
+#ifdef NOLEX
+                               fprintf(stderr, "'%s' was not compiled to support lexicographic ordering\n", argv[0]);
+#else
+                               lexical = 1;
+#endif /* NOLEX */
+                               break;
+                       case 'O':
+                               needInt = &principleCost;
+                               break;
+                       case 'c':
+                               needInt = &prevent_divergence;
+                               break;
+                       case 'e':
+                               needInt = &exceptionTolerance;
+                               break;
+                       case 'd':
+                               diagnostics = 1;
+                               break;
+                       case 'S':
+                               speedflag = 1;
+                               break;
+                       case 't':
+                               trimflag = 1;
+                               break;
+                       case 'G':
+                               grammarflag = 1;
+                               break;
+                       default:
+                               fprintf(stderr, "Bad option (%s)\n", argv[i]);
+                               exit(1);
+                       }
+               } else {
+                       if (inFileName) {
+                               fprintf(stderr, "Unexpected Filename (%s) after (%s)\n", argv[i], inFileName);
+                               exit(1);
+                       }
+                       inFileName = argv[i];
+               }
+               if (needInt || needStr) {
+                       char *v;
+                       char *opt = argv[i];
+
+                       if (argv[i][2]) {
+                               v = &argv[i][2];
+                       } else {
+                               v = argv[++i];
+                               if (!v) {
+                                       fprintf(stderr, "Expection argument after %s\n", opt);
+                                       exit(1);
+                               }
+                       }
+                       if (needInt) {
+                               *needInt = atoi(v);
+                       } else if (needStr) {
+                               *needStr = v;
+                       }
+               }
+       }
+
+       if (inFileName) {
+               if(freopen(inFileName, "r", stdin)==NULL) {
+                       fprintf(stderr, "Failed opening (%s)", inFileName);
+                       exit(1);
+               }
+       }
+
+       if (outFileName) {
+               if ((outfile = fopen(outFileName, "w")) == NULL) {
+                       fprintf(stderr, "Failed opening (%s)", outFileName);
+                       exit(1);
+               }
+       } else {
+               outfile = stdout;
+       }
+
+
+       yyparse();
+
+       if (!rules) {
+               fprintf(stderr, "ERROR: No rules present\n");
+               exit(1);
+       }
+
+       findChainRules();
+       findAllPairs();
+       doGrammarNts();
+       build();
+
+       debug(debugTables, foreachList((ListFn) dumpOperator_l, operators));
+       debug(debugTables, printf("---final set of states ---\n"));
+       debug(debugTables, dumpMapping(globalMap));
+
+
+       startBurm();
+       makeNts();
+       if (simpleTables) {
+               makeSimple();
+       } else {
+               makePlanks();
+       }
+
+       startOptional();
+       makeLabel();
+       makeKids();
+
+       if (internals) {
+               makeChild();
+               makeOpLabel();
+               makeStateLabel();
+       }
+       endOptional();
+
+       makeOperatorVector();
+       makeNonterminals();
+       if (internals) {
+               makeOperators();
+               makeStringArray();
+               makeRuleDescArray();
+               makeCostArray();
+               makeDeltaCostArray();
+               makeStateStringArray();
+               makeNonterminalArray();
+               /*
+               makeLHSmap();
+               */
+       }
+       makeClosureArray();
+
+       if (diagnostics) {
+               reportDiagnostics();
+       }
+
+       yypurge();
+       exit(0);
+}
diff --git a/utils/Burg/map.c b/utils/Burg/map.c
new file mode 100644 (file)
index 0000000..6c3c154
--- /dev/null
@@ -0,0 +1,135 @@
+char rcsid_map[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+#include "fe.h"
+
+Mapping globalMap;
+
+static void growMapping ARGS((Mapping));
+static int hash ARGS((Item_Set, int));
+
+Mapping
+newMapping(size) int size;
+{
+       Mapping m;
+
+       m = (Mapping) zalloc(sizeof(struct mapping));
+       assert(m);
+
+       m->count = 0;
+       m->hash = (List*) zalloc(size * sizeof(List));
+       m->hash_size = size;
+       m->max_size = STATES_INCR;
+       m->set = (Item_Set*) zalloc(m->max_size * sizeof(Item_Set));
+       assert(m->set);
+
+       return m;
+}
+
+static void
+growMapping(m) Mapping m;
+{
+       Item_Set *tmp;
+
+       m->max_size += STATES_INCR;
+       tmp = (Item_Set*) zalloc(m->max_size * sizeof(Item_Set));
+       memcpy(tmp, m->set, m->count * sizeof(Item_Set));
+       zfree(m->set);
+       m->set = tmp;
+}
+
+static int
+hash(ts, mod) Item_Set ts; int mod;
+{
+       register Item *p = ts->virgin;
+       register int v;
+       register Relevant r = ts->relevant;
+       register int nt;
+
+       if (!ts->op) {
+               return 0;
+       }
+
+       v = 0;
+       for (; (nt = *r) != 0; r++) {
+               v ^= ((int)p[nt].rule) + (PRINCIPLECOST(p[nt].delta)<<4);
+       }
+       v >>= 4;
+       v &= (mod-1);
+       return v;
+}
+
+Item_Set
+encode(m, ts, new) Mapping m; Item_Set ts; int *new;
+{
+       int h;
+       List l;
+
+       assert(m);
+       assert(ts);
+       assert(m->count <= m->max_size);
+
+       if (grammarNts && errorState && m == globalMap) {
+               List l;
+               int found;
+
+               found = 0;
+               for (l = grammarNts; l; l = l->next) {
+                       Symbol s;
+                       s = (Symbol) l->x;
+
+                       if (ts->virgin[s->u.nt->num].rule) {
+                               found = 1;
+                               break;
+                       }
+               }
+               if (!found) {
+                       *new = 0;
+                       return errorState;
+               }
+       }
+
+       *new = 0;
+       h = hash(ts, m->hash_size);
+       for (l = m->hash[h]; l; l = l->next) {
+               Item_Set s = (Item_Set) l->x;
+               if (ts->op == s->op && equivSet(ts, s)) {
+                       ts->num = s->num;
+                       return s;
+               }
+       }
+       if (m->count >= m->max_size) {
+               growMapping(m);
+       }
+       assert(m->count < m->max_size);
+       m->set[m->count] = ts;
+       ts->num = m->count++;
+       *new = 1;
+       m->hash[h] = newList(ts, m->hash[h]);
+       return ts;
+}
+
+Item_Set
+decode(m, t) Mapping m; ItemSetNum t;
+{
+       assert(m);
+       assert(t);
+       assert(m->count < m->max_size);
+       assert(t < m->count);
+
+       return m->set[t];
+}
+
+void
+dumpMapping(m) Mapping m;
+{
+       int i;
+
+       printf("BEGIN Mapping: Size=%d\n", m->count);
+       for (i = 0; i < m->count; i++) {
+               dumpItem_Set(m->set[i]);
+       }
+       printf("END Mapping\n");
+}
diff --git a/utils/Burg/nonterminal.c b/utils/Burg/nonterminal.c
new file mode 100644 (file)
index 0000000..af88dd6
--- /dev/null
@@ -0,0 +1,49 @@
+char rcsid_nonterminal[] = "$Id$";
+
+#include "b.h"
+#include <stdio.h>
+
+NonTerminal    start;
+NonTerminalNum max_nonterminal = 1;
+NonTerminalNum last_user_nonterminal;
+List           nonterminals;
+
+NonTerminal
+newNonTerminal(name) char *name;
+{
+       NonTerminal nt;
+
+       nt = (NonTerminal) zalloc(sizeof(struct nonterminal));
+       assert(nt);
+       if (max_nonterminal == 1) {
+               start = nt;
+       }
+       nt->name = name;
+       nt->num = max_nonterminal++;
+       nonterminals = newList(nt, nonterminals);
+
+       return nt;
+}
+
+int
+nonTerminalName(buf, i) char *buf; int i;
+{
+       List l;
+       extern char *strcpy ARGS((char *, char *));
+
+       for (l = nonterminals; l; l = l->next) {
+               NonTerminal nt = (NonTerminal) l->x;
+               if (nt->num == i) {
+                       strcpy(buf, nt->name);
+                       return 1;
+               }
+       }
+       strcpy(buf, "(Unknown NonTerminal)");
+       return 0;
+}
+
+void
+dumpNonTerminal(n) NonTerminal n;
+{
+       printf("%s(%d)", n->name, n->num);
+}
diff --git a/utils/Burg/operator.c b/utils/Burg/operator.c
new file mode 100644 (file)
index 0000000..a6df9e3
--- /dev/null
@@ -0,0 +1,48 @@
+char rcsid_operator[] = "$Id$";
+
+#include "b.h"
+#include <stdio.h>
+
+int max_arity = -1;
+
+List operators;
+List leaves;
+
+Operator
+newOperator(name, num, arity) char *name; OperatorNum num; ArityNum arity;
+{
+       Operator op;
+
+       assert(arity <= MAX_ARITY);
+       op = (Operator) zalloc(sizeof(struct operator));
+       assert(op);
+       op->name = name;
+       op->num = num;
+       op->arity = arity;
+
+       operators = newList(op, operators);
+
+       return op;
+}
+
+void
+dumpOperator_s(op) Operator op;
+{
+       printf("Op: %s(%d)=%d\n", op->name, op->arity, op->num);
+}
+
+void
+dumpOperator(op, full) Operator op; int full;
+{
+       dumpOperator_s(op);
+       if (full) {
+               dumpTable(op->table, 0);
+       }
+}
+
+void
+dumpOperator_l(op) Operator op;
+{
+       dumpOperator(op, 1);
+}
+
diff --git a/utils/Burg/pattern.c b/utils/Burg/pattern.c
new file mode 100644 (file)
index 0000000..472aca5
--- /dev/null
@@ -0,0 +1,38 @@
+char rcsid_pattern[] = "$Id$";
+
+#include <stdio.h>
+#include "b.h"
+
+Pattern
+newPattern(op) Operator op;
+{
+       Pattern p;
+
+       p = (Pattern) zalloc(sizeof(struct pattern));
+       p->op = op;
+       return p;
+}
+
+void
+dumpPattern(p) Pattern p;
+{
+       int i;
+
+       if (!p) {
+               printf("[no-pattern]");
+               return;
+       }
+
+       if (p->op) {
+               printf("%s", p->op->name);
+               if (p->op->arity > 0) {
+                       printf("(");
+                       for (i = 0; i < p->op->arity; i++) {
+                               printf("%s ", p->children[i]->name);
+                       }
+                       printf(")");
+               }
+       } else {
+               printf("%s", p->children[0]->name);
+       }
+}
diff --git a/utils/Burg/plank.c b/utils/Burg/plank.c
new file mode 100644 (file)
index 0000000..053304e
--- /dev/null
@@ -0,0 +1,920 @@
+char rcsid_plank[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+#include "fe.h"
+
+#define ERROR_VAL 0
+
+int speedflag = 0;
+
+Item_Set *sortedStates;
+static struct stateMapTable smt;
+int exceptionTolerance = 0;
+static int plankSize = 32;
+
+static Plank newPlank ARGS((void));
+static PlankMap newPlankMap ARGS((int));
+static StateMap newStateMap ARGS((void));
+static Exception newException ARGS((int, int));
+static void enterStateMap ARGS((PlankMap, short *, int, int *));
+static List assemblePlanks ARGS((void));
+static void assignRules ARGS((RuleAST));
+static int stateCompare ARGS((Item_Set *, Item_Set *));
+static int ruleCompare ARGS((RuleAST *, RuleAST *));
+static void renumber ARGS((void));
+static short * newVector ARGS((void));
+static int width ARGS((int));
+static PlankMap mapToPmap ARGS((Dimension));
+static void doDimPmaps ARGS((Operator));
+static void doNonTermPmaps ARGS((NonTerminal));
+static void makePmaps ARGS((void));
+static void outPlank ARGS((Plank));
+static void purgePlanks ARGS((List));
+static void inToEx ARGS((void));
+static void makePlankRuleMacros ARGS((void));
+static void makePlankRule ARGS((void));
+static void exceptionSwitch ARGS((List, char *, char *, char *, int, char *));
+static void doPlankLabel ARGS((Operator));
+static void doPlankLabelSafely ARGS((Operator));
+static void doPlankLabelMacrosSafely ARGS((Operator));
+static void makePlankState ARGS((void));
+
+static Plank
+newPlank()
+{
+       Plank p;
+       char buf[50];
+       static int num = 0;
+
+       p = (Plank) zalloc(sizeof(struct plank));
+       sprintf(buf, "%s_plank_%d", prefix, num++);
+       p->name = (char *) zalloc(strlen(buf)+1);
+       strcpy(p->name, buf);
+       return p;
+}
+
+static PlankMap
+newPlankMap(offset) int offset;
+{
+       PlankMap im;
+
+       im = (PlankMap) zalloc(sizeof(struct plankMap));
+       im->offset = offset;
+       return im;
+}
+
+static StateMap
+newStateMap()
+{
+       char buf[50];
+       static int num = 0;
+
+       StateMap sm;
+
+       sm = (StateMap) zalloc(sizeof(struct stateMap));
+       sprintf(buf, "f%d", num++);
+       sm->fieldname = (char *) zalloc(strlen(buf)+1);
+       strcpy(sm->fieldname, buf);
+       return sm;
+}
+
+static Exception
+newException(index, value) int index; int value;
+{
+       Exception e;
+
+       e = (Exception) zalloc(sizeof(struct except));
+       e->index = index;
+       e->value = value;
+       return e;
+}
+
+static void
+enterStateMap(im, v, width, new) PlankMap im; short * v; int width; int *new;
+{
+       int i;
+       StateMap sm;
+       List l;
+       int size;
+
+       assert(im);
+       assert(v);
+       assert(width > 0);
+       size = globalMap->count;
+
+       for (l = smt.maps; l; l = l->next) {
+               int ecount;
+
+               sm = (StateMap) l->x;
+               ecount = 0;
+               for (i = 0; i < size; i++) {
+                       if (v[i] != -1 && sm->value[i] != -1 && v[i] != sm->value[i]) {
+                               if (++ecount > exceptionTolerance) {
+                                       goto again;
+                               }
+                       }
+               }
+               for (i = 0; i < size; i++) {
+                       assert(v[i] >= 0);
+                       assert(sm->value[i] >= 0);
+                       if (v[i] == -1) {
+                               continue;
+                       }
+                       if (sm->value[i] == -1) {
+                               sm->value[i] = v[i];
+                       } else if (v[i] != sm->value[i]) {
+                               im->exceptions = newList(newException(i,v[i]), im->exceptions);
+                       }
+               }
+               im->values = sm;
+               if (width > sm->width) {
+                       sm->width = width;
+               }
+               *new = 0;
+               return;
+       again: ;
+       }
+       sm = newStateMap();
+       im->values = sm;
+       sm->value = v;
+       sm->width = width;
+       *new = 1;
+       smt.maps = newList(sm, smt.maps);
+}
+
+static List
+assemblePlanks()
+{
+       List planks = 0;
+       Plank pl;
+       List p;
+       List s;
+
+       for (s = smt.maps; s; s = s->next) {
+               StateMap sm = (StateMap) s->x;
+               for (p = planks; p; p = p->next) {
+                       pl = (Plank) p->x;
+                       if (sm->width <= plankSize - pl->width) {
+                               pl->width += sm->width;
+                               pl->fields = newList(sm, pl->fields);
+                               sm->plank = pl;
+                               goto next;
+                       }
+               }
+               pl = newPlank();
+               pl->width = sm->width;
+               pl->fields = newList(sm, 0);
+               sm->plank = pl;
+               planks = appendList(pl, planks);
+       next: ;
+       }
+       return planks;
+}
+
+RuleAST *sortedRules;
+
+static int count;
+
+static void
+assignRules(ast) RuleAST ast;
+{
+       sortedRules[count++] = ast;
+}
+
+static int
+stateCompare(s, t) Item_Set *s; Item_Set *t;
+{
+       return strcmp((*s)->op->name, (*t)->op->name);
+}
+
+static int
+ruleCompare(s, t) RuleAST *s; RuleAST *t;
+{
+       return strcmp((*s)->lhs, (*t)->lhs);
+}
+
+void
+dumpSortedStates()
+{
+       int i;
+       
+       printf("dump Sorted States: ");
+       for (i = 0; i < globalMap->count; i++) {
+               printf("%d ", sortedStates[i]->num);
+       }
+       printf("\n");
+}
+
+void
+dumpSortedRules()
+{
+       int i;
+       
+       printf("dump Sorted Rules: ");
+       for (i = 0; i < max_ruleAST; i++) {
+               printf("%d ", sortedRules[i]->rule->erulenum);
+       }
+       printf("\n");
+}
+
+static void
+renumber()
+{
+       int i;
+       Operator previousOp;
+       NonTerminal previousLHS;
+       int base_counter;
+
+       sortedStates = (Item_Set*) zalloc(globalMap->count * sizeof(Item_Set));
+       for (i = 1; i < globalMap->count; i++) {
+               sortedStates[i-1] = globalMap->set[i];
+       }
+       qsort(sortedStates, globalMap->count-1, sizeof(Item_Set), stateCompare);
+       previousOp = 0;
+       for (i = 0; i < globalMap->count-1; i++) {
+               sortedStates[i]->newNum = i;
+               sortedStates[i]->op->stateCount++;
+               if (previousOp != sortedStates[i]->op) {
+                       sortedStates[i]->op->baseNum = i;
+                       previousOp = sortedStates[i]->op;
+               }
+       }
+
+       sortedRules = (RuleAST*) zalloc(max_ruleAST * sizeof(RuleAST));
+       count = 0;
+       foreachList((ListFn) assignRules, ruleASTs);
+       qsort(sortedRules, max_ruleAST, sizeof(RuleAST), ruleCompare);
+       previousLHS = 0;
+       base_counter = 0;
+       for (i = 0; i < max_ruleAST; i++) {
+               if (previousLHS != sortedRules[i]->rule->lhs) {
+                       sortedRules[i]->rule->lhs->baseNum = base_counter;
+                       previousLHS = sortedRules[i]->rule->lhs;
+                       base_counter++; /* make space for 0 */
+               }
+               sortedRules[i]->rule->newNum = base_counter;
+               sortedRules[i]->rule->lhs->ruleCount++;
+               sortedRules[i]->rule->lhs->sampleRule = sortedRules[i]->rule; /* kludge for diagnostics */
+               base_counter++;
+       }
+}
+
+static short *
+newVector()
+{
+       short *p;
+       p = (short *) zalloc(globalMap->count* sizeof(short));
+       return p;
+}
+
+static int
+width(v) int v;
+{
+       int c;
+
+       for (c = 0; v; v >>= 1) {
+               c++;
+       }
+       return c;
+
+}
+
+static PlankMap
+mapToPmap(d) Dimension d;
+{
+       PlankMap im;
+       short *v;
+       int i;
+       int new;
+
+       if (d->map->count == 1) {
+               return 0;
+       }
+       assert(d->map->count > 1);
+       im = newPlankMap(0);
+       v = newVector();
+       for (i = 0; i < globalMap->count-1; i++) {
+               int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num;
+               assert(index >= 0);
+               v[i+1] = index;
+       }
+       v[0] = 0;
+       enterStateMap(im, v, width(d->map->count), &new);
+       if (!new) {
+               zfree(v);
+       }
+       return im;
+}
+
+static void
+doDimPmaps(op) Operator op;
+{
+       int i, j;
+       Dimension d;
+       short *v;
+       PlankMap im;
+       int new;
+
+       if (!op->table->rules) {
+               return;
+       }
+       switch (op->arity) {
+       case 0:
+               break;
+       case 1:
+               d = op->table->dimen[0];
+               if (d->map->count > 1) {
+                       v = newVector();
+                       im = newPlankMap(op->baseNum);
+                       for (i = 0; i < globalMap->count-1; i++) {
+                               int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num;
+                               if (index) {
+                                       Item_Set *ts = transLval(op->table, index, 0);
+                                       v[i+1] = (*ts)->newNum - op->baseNum+1;
+                                       assert(v[i+1] >= 0);
+                               }
+                       }
+                       enterStateMap(im, v, width(d->map->count-1), &new);
+                       if (!new) {
+                               zfree(v);
+                       }
+                       d->pmap = im;
+               }
+               break;
+       case 2:
+               if (op->table->dimen[0]->map->count == 1 && op->table->dimen[1]->map->count == 1) {
+                       op->table->dimen[0]->pmap = 0;
+                       op->table->dimen[1]->pmap = 0;
+               } else if (op->table->dimen[0]->map->count == 1) {
+                       v = newVector();
+                       im = newPlankMap(op->baseNum);
+                       d = op->table->dimen[1];
+                       for (i = 0; i < globalMap->count-1; i++) {
+                               int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num;
+                               if (index) {
+                                       Item_Set *ts = transLval(op->table, 1, index);
+                                       v[i+1] = (*ts)->newNum - op->baseNum+1;
+                                       assert(v[i+1] >= 0);
+                               }
+                       }
+                       enterStateMap(im, v, width(d->map->count-1), &new);
+                       if (!new) {
+                               zfree(v);
+                       }
+                       d->pmap = im;
+               } else if (op->table->dimen[1]->map->count == 1) {
+                       v = newVector();
+                       im = newPlankMap(op->baseNum);
+                       d = op->table->dimen[0];
+                       for (i = 0; i < globalMap->count-1; i++) {
+                               int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num;
+                               if (index) {
+                                       Item_Set *ts = transLval(op->table, index, 1);
+                                       v[i +1] = (*ts)->newNum - op->baseNum +1;
+                                       assert(v[i +1] >= 0);
+                               }
+                       }
+                       enterStateMap(im, v, width(d->map->count-1), &new);
+                       if (!new) {
+                               zfree(v);
+                       }
+                       d->pmap = im;
+               } else {
+                       op->table->dimen[0]->pmap = mapToPmap(op->table->dimen[0]);
+                       op->table->dimen[1]->pmap = mapToPmap(op->table->dimen[1]);
+                       /* output table */
+                       fprintf(outfile, "static unsigned %s %s_%s_transition[%d][%d] = {", 
+                               op->stateCount <= 255 ? "char" : "short",
+                               prefix,
+                               op->name,
+                               op->table->dimen[0]->map->count,
+                               op->table->dimen[1]->map->count);
+                       for (i = 0; i < op->table->dimen[0]->map->count; i++) {
+                               if (i > 0) {
+                                       fprintf(outfile, ",");
+                               }
+                               fprintf(outfile, "\n{");
+                               for (j = 0; j < op->table->dimen[1]->map->count; j++) {
+                                       Item_Set *ts = transLval(op->table, i, j);
+                                       short diff;
+                                       if (j > 0) {
+                                               fprintf(outfile, ",");
+                                               if (j % 10 == 0) {
+                                                       fprintf(outfile, "\t/* row %d, cols %d-%d*/\n",
+                                                               i,
+                                                               j-10,
+                                                               j-1);
+                                               }
+                                       }
+                                       if ((*ts)->num > 0) {
+                                               diff = (*ts)->newNum - op->baseNum +1;
+                                       } else {
+                                               diff = 0;
+                                       }
+                                       fprintf(outfile, "%5d", diff);
+                               }
+                               fprintf(outfile, "}\t/* row %d */", i);
+                       }
+                       fprintf(outfile, "\n};\n");
+               }
+               break;
+       default:
+               assert(0);
+       }
+}
+
+static NonTerminal *ntVector;
+
+static void
+doNonTermPmaps(n) NonTerminal n;
+{
+       short *v;
+       PlankMap im;
+       int new;
+       int i;
+
+       ntVector[n->num] = n;
+       if (n->num >= last_user_nonterminal) {
+               return;
+       }
+       if (n->ruleCount <= 0) {
+               return;
+       }
+       im = newPlankMap(n->baseNum);
+       v = newVector();
+       for (i = 0; i < globalMap->count-1; i++) {
+               Rule r = globalMap->set[sortedStates[i]->num]->closed[n->num].rule;
+               if (r) {
+                       r->used = 1;
+                       v[i+1] = r->newNum - n->baseNum /*safely*/;
+                       assert(v[i+1] >= 0);
+               }
+       }
+       enterStateMap(im, v, width(n->ruleCount+1), &new);
+       if (!new) {
+               zfree(v);
+       }
+       n->pmap = im;
+}
+
+static void
+makePmaps()
+{
+       foreachList((ListFn) doDimPmaps, operators);
+       ntVector = (NonTerminal*) zalloc((max_nonterminal) * sizeof(NonTerminal));
+       foreachList((ListFn) doNonTermPmaps, nonterminals);
+}
+
+static void
+outPlank(p) Plank p;
+{
+       List f;
+       int i;
+
+       fprintf(outfile, "static struct {\n");
+
+       for (f = p->fields; f; f = f->next) {
+               StateMap sm = (StateMap) f->x;
+               fprintf(outfile, "\tunsigned int %s:%d;\n", sm->fieldname, sm->width);
+       }
+
+       fprintf(outfile, "} %s[] = {\n", p->name);
+
+       for (i = 0; i < globalMap->count; i++) {
+               fprintf(outfile, "\t{");
+               for (f = p->fields; f; f = f->next) {
+                       StateMap sm = (StateMap) f->x;
+                       fprintf(outfile, "%4d,", sm->value[i] == -1 ? ERROR_VAL : sm->value[i]);
+               }
+               fprintf(outfile, "},\t/* row %d */\n", i);
+       }
+
+       fprintf(outfile, "};\n");
+}
+
+static void
+purgePlanks(planks) List planks;
+{
+       List p;
+
+       for (p = planks; p; p = p->next) {
+               Plank x = (Plank) p->x;
+               outPlank(x);
+       }
+}
+
+static void
+inToEx()
+{
+       int i;
+       int counter;
+
+       fprintf(outfile, "static short %s_eruleMap[] = {\n", prefix);
+       counter = 0;
+       for (i = 0; i < max_ruleAST; i++) {
+               if (counter > 0) {
+                       fprintf(outfile, ",");
+                       if (counter % 10 == 0) {
+                               fprintf(outfile, "\t/* %d-%d */\n", counter-10, counter-1);
+                       }
+               }
+               if (counter < sortedRules[i]->rule->newNum) {
+                       assert(counter == sortedRules[i]->rule->newNum-1);
+                       fprintf(outfile, "%5d", 0);
+                       counter++;
+                       if (counter > 0) {
+                               fprintf(outfile, ",");
+                               if (counter % 10 == 0) {
+                                       fprintf(outfile, "\t/* %d-%d */\n", counter-10, counter-1);
+                               }
+                       }
+               }
+               fprintf(outfile, "%5d", sortedRules[i]->rule->erulenum);
+               counter++;
+       }
+       fprintf(outfile, "\n};\n");
+}
+
+static void
+makePlankRuleMacros()
+{
+       int i;
+
+       for (i = 1; i < last_user_nonterminal; i++) {
+               List es;
+               PlankMap im = ntVector[i]->pmap;
+               fprintf(outfile, "#define %s_%s_rule(state)\t", prefix, ntVector[i]->name);
+               if (im) {
+                       fprintf(outfile, "%s_eruleMap[", prefix);
+                       for (es = im->exceptions; es; es = es->next) {
+                               Exception e = (Exception) es->x;
+                               fprintf(outfile, "((state) == %d ? %d :", 
+                                               e->index, e->value);
+                       }
+                       fprintf(outfile, "%s[state].%s", 
+                               im->values->plank->name, 
+                               im->values->fieldname);
+                       for (es = im->exceptions; es; es = es->next) {
+                               fprintf(outfile, ")");
+                       }
+                       fprintf(outfile, " +%d]", im->offset);
+
+               } else {
+                       /* nonterminal never appears on LHS. */
+                       assert(ntVector[i] ==  start);
+                       fprintf(outfile, "0");
+               }
+               fprintf(outfile, "\n");
+       }
+       fprintf(outfile, "\n");
+}
+
+static void
+makePlankRule()
+{
+       int i;
+
+       makePlankRuleMacros();
+
+       fprintf(outfile, "#ifdef __STDC__\n");
+       fprintf(outfile, "int %s_rule(int state, int goalnt) {\n", prefix);
+       fprintf(outfile, "#else\n");
+       fprintf(outfile, "int %s_rule(state, goalnt) int state; int goalnt; {\n", prefix);
+       fprintf(outfile, "#endif\n");
+
+       fprintf(outfile, 
+       "\t%s_assert(state >= 0 && state < %d, %s_PANIC(\"Bad state %%d passed to %s_rule\\n\", state));\n",
+                               prefix, globalMap->count, prefix, prefix);
+       fprintf(outfile, "\tswitch(goalnt) {\n");
+
+       for (i = 1; i < last_user_nonterminal; i++) {
+               fprintf(outfile, "\tcase %d:\n", i);
+               fprintf(outfile, "\t\treturn %s_%s_rule(state);\n", prefix, ntVector[i]->name);
+       }
+       fprintf(outfile, "\tdefault:\n");
+       fprintf(outfile, "\t\t%s_PANIC(\"Unknown nonterminal %%d in %s_rule;\\n\", goalnt);\n", prefix, prefix);
+       fprintf(outfile, "\t\tabort();\n");
+       fprintf(outfile, "\t\treturn 0;\n");
+       fprintf(outfile, "\t}\n");
+       fprintf(outfile, "}\n");
+}
+
+static void
+exceptionSwitch(es, sw, pre, post, offset, def) List es; char *sw; char *pre; char *post; int offset; char *def;
+{
+       if (es) {
+               fprintf(outfile, "\t\tswitch (%s) {\n", sw);
+               for (; es; es = es->next) {
+                       Exception e = (Exception) es->x;
+                       fprintf(outfile, "\t\tcase %d: %s %d; %s\n", e->index, pre, e->value+offset, post);
+               }
+               if (def) {
+                       fprintf(outfile, "\t\tdefault: %s;\n", def);
+               }
+               fprintf(outfile, "\t\t}\n");
+       } else {
+               if (def) {
+                       fprintf(outfile, "\t\t%s;\n", def);
+               }
+       }
+}
+
+static void
+doPlankLabel(op) Operator op;
+{
+       PlankMap im0;
+       PlankMap im1;
+       char buf[100];
+
+       fprintf(outfile, "\tcase %d:\n", op->num);
+       switch (op->arity) {
+       case 0:
+               fprintf(outfile, "\t\treturn %d;\n", op->table->transition[0]->newNum);
+               break;
+       case 1:
+               im0 = op->table->dimen[0]->pmap;
+               if (im0) {
+                       exceptionSwitch(im0->exceptions, "l", "return ", "", im0->offset, 0);
+                       fprintf(outfile, "\t\treturn %s[l].%s + %d;\n", 
+                               im0->values->plank->name, im0->values->fieldname, im0->offset);
+               } else {
+                       Item_Set *ts = transLval(op->table, 1, 0);
+                       if (*ts) {
+                               fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum);
+                       } else {
+                               fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL);
+                       }
+               }
+               break;
+       case 2:
+               im0 = op->table->dimen[0]->pmap;
+               im1 = op->table->dimen[1]->pmap;
+               if (!im0 && !im1) {
+                       Item_Set *ts = transLval(op->table, 1, 1);
+                       if (*ts) {
+                               fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum);
+                       } else {
+                               fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL);
+                       }
+               } else if (!im0) {
+                       exceptionSwitch(im1->exceptions, "r", "return ", "", im1->offset, 0);
+                       fprintf(outfile, "\t\treturn %s[r].%s + %d;\n", 
+                               im1->values->plank->name, im1->values->fieldname, im1->offset);
+               } else if (!im1) {
+                       exceptionSwitch(im0->exceptions, "l", "return ", "", im0->offset, 0);
+                       fprintf(outfile, "\t\treturn %s[l].%s + %d;\n", 
+                               im0->values->plank->name, im0->values->fieldname, im0->offset);
+               } else {
+                       assert(im0->offset == 0);
+                       assert(im1->offset == 0);
+                       sprintf(buf, "l = %s[l].%s",
+                               im0->values->plank->name, im0->values->fieldname);
+                       exceptionSwitch(im0->exceptions, "l", "l =", "break;", 0, buf);
+                       sprintf(buf, "r = %s[r].%s",
+                               im1->values->plank->name, im1->values->fieldname);
+                       exceptionSwitch(im1->exceptions, "r", "r =", "break;", 0, buf);
+
+                       fprintf(outfile, "\t\treturn %s_%s_transition[l][r] + %d;\n", 
+                               prefix,
+                               op->name,
+                               op->baseNum);
+               }
+               break;
+       default:
+               assert(0);
+       }
+}
+
+static void
+doPlankLabelMacrosSafely(op) Operator op;
+{
+       PlankMap im0;
+       PlankMap im1;
+
+       switch (op->arity) {
+       case -1:
+               fprintf(outfile, "#define %s_%s_state\t0\n", prefix, op->name);
+               break;
+       case 0:
+               fprintf(outfile, "#define %s_%s_state", prefix, op->name);
+               fprintf(outfile, "\t%d\n", op->table->transition[0]->newNum+1);
+               break;
+       case 1:
+               fprintf(outfile, "#define %s_%s_state(l)", prefix, op->name);
+               im0 = op->table->dimen[0]->pmap;
+               if (im0) {
+                       if (im0->exceptions) {
+                               List es = im0->exceptions;
+                               assert(0);
+                               fprintf(outfile, "\t\tswitch (l) {\n");
+                               for (; es; es = es->next) {
+                                       Exception e = (Exception) es->x;
+                                       fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im0->offset : 0);
+                               }
+                               fprintf(outfile, "\t\t}\n");
+                       }
+                       if (speedflag) {
+                               fprintf(outfile, "\t( %s[l].%s + %d )\n",
+                                       im0->values->plank->name, im0->values->fieldname,
+                                       im0->offset);
+                       } else {
+                               fprintf(outfile, "\t( (%s_TEMP = %s[l].%s) ? %s_TEMP + %d : 0 )\n",
+                                       prefix,
+                                       im0->values->plank->name, im0->values->fieldname,
+                                       prefix,
+                                       im0->offset);
+                       }
+               } else {
+                       Item_Set *ts = transLval(op->table, 1, 0);
+                       if (*ts) {
+                               fprintf(outfile, "\t%d\n", (*ts)->newNum+1);
+                       } else {
+                               fprintf(outfile, "\t%d\n", 0);
+                       }
+               }
+               break;
+       case 2:
+               fprintf(outfile, "#define %s_%s_state(l,r)", prefix, op->name);
+
+               im0 = op->table->dimen[0]->pmap;
+               im1 = op->table->dimen[1]->pmap;
+               if (!im0 && !im1) {
+                       Item_Set *ts = transLval(op->table, 1, 1);
+                       assert(0);
+                       if (*ts) {
+                               fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum+1);
+                       } else {
+                               fprintf(outfile, "\t\treturn %d;\n", 0);
+                       }
+               } else if (!im0) {
+                       assert(0);
+                       if (im1->exceptions) {
+                               List es = im1->exceptions;
+                               fprintf(outfile, "\t\tswitch (r) {\n");
+                               for (; es; es = es->next) {
+                                       Exception e = (Exception) es->x;
+                                       fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im1->offset : 0);
+                               }
+                               fprintf(outfile, "\t\t}\n");
+                       }
+                       fprintf(outfile, "\t\tstate = %s[r].%s; offset = %d;\n", 
+                               im1->values->plank->name, im1->values->fieldname, im1->offset);
+                       fprintf(outfile, "\t\tbreak;\n");
+               } else if (!im1) {
+                       assert(0);
+                       if (im0->exceptions) {
+                               List es = im0->exceptions;
+                               fprintf(outfile, "\t\tswitch (l) {\n");
+                               for (; es; es = es->next) {
+                                       Exception e = (Exception) es->x;
+                                       fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im0->offset : 0);
+                               }
+                               fprintf(outfile, "\t\t}\n");
+                       }
+                       fprintf(outfile, "\t\tstate = %s[l].%s; offset = %d;\n", 
+                               im0->values->plank->name, im0->values->fieldname, im0->offset);
+                       fprintf(outfile, "\t\tbreak;\n");
+               } else {
+                       assert(im0->offset == 0);
+                       assert(im1->offset == 0);
+                       /*
+                       sprintf(buf, "l = %s[l].%s",
+                               im0->values->plank->name, im0->values->fieldname);
+                       exceptionSwitch(im0->exceptions, "l", "l =", "break;", 0, buf);
+                       sprintf(buf, "r = %s[r].%s",
+                               im1->values->plank->name, im1->values->fieldname);
+                       exceptionSwitch(im1->exceptions, "r", "r =", "break;", 0, buf);
+
+                       fprintf(outfile, "\t\tstate = %s_%s_transition[l][r]; offset = %d;\n", 
+                               prefix,
+                               op->name,
+                               op->baseNum);
+                       fprintf(outfile, "\t\tbreak;\n");
+                       */
+
+                       if (speedflag) {
+                               fprintf(outfile, "\t( %s_%s_transition[%s[l].%s][%s[r].%s] + %d)\n",
+                                       prefix,
+                                       op->name,
+                                       im0->values->plank->name, im0->values->fieldname,
+                                       im1->values->plank->name, im1->values->fieldname,
+                                       op->baseNum);
+                       } else {
+                               fprintf(outfile, "\t( (%s_TEMP = %s_%s_transition[%s[l].%s][%s[r].%s]) ? ",
+                                       prefix,
+                                       prefix,
+                                       op->name,
+                                       im0->values->plank->name, im0->values->fieldname,
+                                       im1->values->plank->name, im1->values->fieldname);
+                               fprintf(outfile, "%s_TEMP + %d : 0 )\n",
+                                       prefix,
+                                       op->baseNum);
+                       }
+               }
+               break;
+       default:
+               assert(0);
+       }
+}
+static void
+doPlankLabelSafely(op) Operator op;
+{
+       fprintf(outfile, "\tcase %d:\n", op->num);
+       switch (op->arity) {
+       case -1:
+               fprintf(outfile, "\t\treturn 0;\n");
+               break;
+       case 0:
+               fprintf(outfile, "\t\treturn %s_%s_state;\n", prefix, op->name);
+               break;
+       case 1:
+               fprintf(outfile, "\t\treturn %s_%s_state(l);\n", prefix, op->name);
+               break;
+       case 2:
+               fprintf(outfile, "\t\treturn %s_%s_state(l,r);\n", prefix, op->name);
+               break;
+       default:
+               assert(0);
+       }
+}
+
+static void
+makePlankState()
+{
+       fprintf(outfile, "\n");
+       fprintf(outfile, "int %s_TEMP;\n", prefix);
+       foreachList((ListFn) doPlankLabelMacrosSafely, operators);
+       fprintf(outfile, "\n");
+
+       fprintf(outfile, "#ifdef __STDC__\n");
+       switch (max_arity) {
+       case -1:
+               fprintf(stderr, "ERROR: no terminals in grammar.\n");
+               exit(1);
+       case 0:
+               fprintf(outfile, "int %s_state(int op) {\n", prefix);
+               fprintf(outfile, "#else\n");
+               fprintf(outfile, "int %s_state(op) int op; {\n", prefix);
+               break;
+       case 1:
+               fprintf(outfile, "int %s_state(int op, int l) {\n", prefix);
+               fprintf(outfile, "#else\n");
+               fprintf(outfile, "int %s_state(op, l) int op; int l; {\n", prefix);
+               break;
+       case 2:
+               fprintf(outfile, "int %s_state(int op, int l, int r) {\n", prefix);
+               fprintf(outfile, "#else\n");
+               fprintf(outfile, "int %s_state(op, l, r) int op; int l; int r; {\n", prefix);
+               break;
+       default:
+               assert(0);
+       }
+       fprintf(outfile, "#endif\n");
+
+       fprintf(outfile, "\tregister int %s_TEMP;\n", prefix);
+
+       fprintf(outfile, "#ifndef NDEBUG\n");
+
+       fprintf(outfile, "\tswitch (op) {\n");
+       opsOfArity(2);
+       if (max_arity >= 2) {
+               fprintf(outfile, 
+               "\t\t%s_assert(r >= 0 && r < %d, %s_PANIC(\"Bad state %%d passed to %s_state\\n\", r));\n",
+                               prefix, globalMap->count, prefix, prefix);
+               fprintf(outfile, "\t\t/*FALLTHROUGH*/\n");
+       }
+       opsOfArity(1);
+       if (max_arity > 1) {
+               fprintf(outfile, 
+               "\t\t%s_assert(l >= 0 && l < %d, %s_PANIC(\"Bad state %%d passed to %s_state\\n\", l));\n",
+                               prefix, globalMap->count, prefix, prefix);
+               fprintf(outfile, "\t\t/*FALLTHROUGH*/\n");
+       }
+       opsOfArity(0);
+       fprintf(outfile, "\t\tbreak;\n");
+       fprintf(outfile, "\t}\n");
+       fprintf(outfile, "#endif\n");
+
+       fprintf(outfile, "\tswitch (op) {\n");
+       fprintf(outfile,"\tdefault: %s_PANIC(\"Unknown op %%d in %s_state\\n\", op); abort(); return 0;\n",
+               prefix, prefix);
+       foreachList((ListFn) doPlankLabelSafely, operators);
+       fprintf(outfile, "\t}\n");
+
+       fprintf(outfile, "}\n");
+}
+
+void
+makePlanks()
+{
+       List planks;
+       renumber();
+       makePmaps();
+       planks = assemblePlanks();
+       purgePlanks(planks);
+       inToEx();
+       makePlankRule();
+       makePlankState();
+}
diff --git a/utils/Burg/queue.c b/utils/Burg/queue.c
new file mode 100644 (file)
index 0000000..76e5ea9
--- /dev/null
@@ -0,0 +1,64 @@
+char rcsid_queue[] = "$Id$";
+
+#include "b.h"
+#include <stdio.h>
+
+Queue globalQ;
+
+Queue
+newQ()
+{
+       Queue q;
+
+       q = (Queue) zalloc(sizeof(struct queue));
+       assert(q);
+       q->head = 0;
+       q->tail = 0;
+
+       return q;
+}
+
+void
+addQ(q, ts) Queue q; Item_Set ts;
+{
+       List qe;
+
+       assert(q);
+       assert(ts);
+
+       qe = newList(ts, 0);
+       if (q->head) {
+               assert(q->tail);
+               q->tail->next = qe;
+               q->tail = qe;
+       } else {
+               q->head = q->tail = qe;
+       }
+}
+
+Item_Set
+popQ(q) Queue q;
+{
+       List qe;
+       Item_Set ts;
+
+       assert(q);
+
+       if (q->head) {
+               qe = q->head;
+               q->head = q->head->next;
+               ts = (Item_Set) qe->x;
+               zfree(qe);
+               return ts;
+       } else {
+               return 0;
+       }
+}
+
+void
+dumpQ(q) Queue q;
+{
+       printf("Begin Queue\n");
+       foreachList((ListFn)dumpItem_Set, q->head);
+       printf("End Queue\n");
+}
diff --git a/utils/Burg/rule.c b/utils/Burg/rule.c
new file mode 100644 (file)
index 0000000..ee5c89e
--- /dev/null
@@ -0,0 +1,49 @@
+char rcsid_rule[] = "$Id$";
+
+#include "b.h"
+#include <stdio.h>
+
+RuleNum max_rule;
+int max_erule_num;
+
+struct rule stub_rule;
+
+List rules;
+
+Rule
+newRule(delta, erulenum, lhs, pat) DeltaPtr delta; ERuleNum erulenum; NonTerminal lhs; Pattern pat;
+{
+       Rule p;
+
+       p = (Rule) zalloc(sizeof(struct rule));
+       assert(p);
+       ASSIGNCOST(p->delta, delta);
+       p->erulenum = erulenum;
+       if (erulenum > max_erule_num) {
+               max_erule_num = erulenum;
+       }
+       p->num = max_rule++;
+       p->lhs = lhs;
+       p->pat = pat;
+
+       rules = newList(p, rules);
+
+       return p;
+}
+
+void
+dumpRule(p) Rule p;
+{
+       dumpNonTerminal(p->lhs);
+       printf(" : ");
+       dumpPattern(p->pat);
+       printf(" ");
+       dumpCost(p->delta);
+       printf("\n");
+}
+
+void
+dumpRuleList(l) List l;
+{
+       foreachList((ListFn)dumpRule, l);
+}
diff --git a/utils/Burg/sample.gr b/utils/Burg/sample.gr
new file mode 100644 (file)
index 0000000..e1f7283
--- /dev/null
@@ -0,0 +1,150 @@
+%{
+#include <stdio.h>
+
+typedef struct node *NODEPTR_TYPE;
+
+struct node {
+       int op, state_label;
+       NODEPTR_TYPE left, right;
+};
+
+#define OP_LABEL(p)    ((p)->op)
+#define STATE_LABEL(p) ((p)->state_label)
+#define LEFT_CHILD(p)  ((p)->left)
+#define RIGHT_CHILD(p) ((p)->right)
+#define PANIC          printf
+%}
+
+%start reg
+%term Assign=1 Constant=2 Fetch=3 Four=4 Mul=5 Plus=6
+%%
+con:  Constant                = 1 (0);
+con:  Four                    = 2 (0);
+addr: con                     = 3 (0);
+addr: Plus(con,reg)           = 4 (0);
+addr: Plus(con,Mul(Four,reg)) = 5 (0);
+reg:  Fetch(addr)             = 6 (1);
+reg:  Assign(addr,reg)        = 7 (1);
+
+%%
+
+#define Assign 1
+#define Constant 2
+#define Fetch 3
+#define Four 4
+#define Mul 5
+#define Plus 6
+
+#ifdef __STDC__
+#define ARGS(x) x
+#else
+#define ARGS(x) ()
+#endif
+
+NODEPTR_TYPE buildtree ARGS((int, NODEPTR_TYPE, NODEPTR_TYPE));
+void printcover ARGS((NODEPTR_TYPE, int, int));
+void printtree ARGS((NODEPTR_TYPE));
+int treecost ARGS((NODEPTR_TYPE, int, int));
+void printMatches ARGS((NODEPTR_TYPE));
+int main ARGS((void));
+
+NODEPTR_TYPE buildtree(op, left, right) int op; NODEPTR_TYPE left; NODEPTR_TYPE right; {
+       NODEPTR_TYPE p;
+       extern void *malloc ARGS((unsigned));
+
+       p = (NODEPTR_TYPE) malloc(sizeof *p);
+       p->op = op;
+       p->left = left;
+       p->right = right;
+       return p;
+}
+
+void printcover(p, goalnt, indent) NODEPTR_TYPE p; int goalnt; int indent; {
+       int eruleno = burm_rule(STATE_LABEL(p), goalnt);
+       short *nts = burm_nts[eruleno];
+       NODEPTR_TYPE kids[10];
+       int i;
+       
+       if (eruleno == 0) {
+               printf("no cover\n");
+               return;
+       }
+       for (i = 0; i < indent; i++)
+               printf(".");
+       printf("%s\n", burm_string[eruleno]);
+       burm_kids(p, eruleno, kids);
+       for (i = 0; nts[i]; i++)
+               printcover(kids[i], nts[i], indent+1);
+}
+
+void printtree(p) NODEPTR_TYPE p; {
+       int op = burm_op_label(p);
+
+       printf("%s", burm_opname[op]);
+       switch (burm_arity[op]) {
+       case 0:
+               break;
+       case 1:
+               printf("(");
+               printtree(burm_child(p, 0));
+               printf(")");
+               break;
+       case 2:
+               printf("(");
+               printtree(burm_child(p, 0));
+               printf(", ");
+               printtree(burm_child(p, 1));
+               printf(")");
+               break;
+       }
+}
+
+int treecost(p, goalnt, costindex) NODEPTR_TYPE p; int goalnt; int costindex; {
+       int eruleno = burm_rule(STATE_LABEL(p), goalnt);
+       int cost = burm_cost[eruleno][costindex], i;
+       short *nts = burm_nts[eruleno];
+       NODEPTR_TYPE kids[10];
+
+       burm_kids(p, eruleno, kids);
+       for (i = 0; nts[i]; i++)
+               cost += treecost(kids[i], nts[i], costindex);
+       return cost;
+}
+
+void printMatches(p) NODEPTR_TYPE p; {
+       int nt;
+       int eruleno;
+
+       printf("Node 0x%lx= ", (unsigned long)p);
+       printtree(p);
+       printf(" matched rules:\n");
+       for (nt = 1; burm_ntname[nt] != (char*)NULL; nt++)
+               if ((eruleno = burm_rule(STATE_LABEL(p), nt)) != 0)
+                       printf("\t%s\n", burm_string[eruleno]);
+}
+
+main() {
+       NODEPTR_TYPE p;
+
+       p = buildtree(Assign,
+               buildtree(Constant, 0, 0),
+               buildtree(Fetch,
+                       buildtree(Plus,
+                               buildtree(Constant, 0, 0),
+                               buildtree(Mul,
+                                       buildtree(Four, 0, 0),
+                                       buildtree(Fetch, buildtree(Constant, 0, 0), 0)
+                               )
+                       ),
+                       0
+               )
+       );
+       printtree(p);
+       printf("\n\n");
+       burm_label(p);
+       printcover(p, 1, 0);
+       printf("\nCover cost == %d\n\n", treecost(p, 1, 0));
+       printMatches(p);
+       return 0;
+}
+
diff --git a/utils/Burg/string.c b/utils/Burg/string.c
new file mode 100644 (file)
index 0000000..9b69c30
--- /dev/null
@@ -0,0 +1,65 @@
+char rcsid_string[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+#include "fe.h"
+
+static StrTableElement newStrTableElement ARGS((void));
+
+StrTable
+newStrTable()
+{
+       return (StrTable) zalloc(sizeof(struct strTable));
+}
+
+static StrTableElement
+newStrTableElement()
+{
+       return (StrTableElement) zalloc(sizeof(struct strTableElement));
+}
+
+void
+dumpStrTable(t) StrTable t;
+{ 
+       List e;
+       IntList r;
+
+       printf("Begin StrTable\n");
+       for (e = t->elems; e; e = e->next) {
+               StrTableElement el = (StrTableElement) e->x;
+               printf("%s: ", el->str);
+               for (r = el->erulenos; r; r = r->next) {
+                       int i = r->x;
+                       printf("(%d)", i);
+               }
+               printf("\n");
+       }
+       printf("End StrTable\n");
+}
+
+StrTableElement
+addString(t, s, eruleno, new) StrTable t; char *s; int eruleno; int *new;
+{
+       List l;
+       StrTableElement ste;
+
+       assert(t);
+       for (l = t->elems; l; l = l->next) {
+               StrTableElement e = (StrTableElement) l->x;
+
+               assert(e);
+               if (!strcmp(s, e->str)) {
+                       e->erulenos = newIntList(eruleno, e->erulenos);
+                       *new = 0;
+                       return e;
+               }
+       }
+       ste = newStrTableElement();
+       ste->erulenos = newIntList(eruleno, 0);
+       ste->str = (char *) zalloc(strlen(s) + 1);
+       strcpy(ste->str, s);
+       t->elems = newList(ste, t->elems);
+       *new = 1;
+       return ste;
+}
diff --git a/utils/Burg/symtab.c b/utils/Burg/symtab.c
new file mode 100644 (file)
index 0000000..3ecab2f
--- /dev/null
@@ -0,0 +1,38 @@
+char rcsid_symtab[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+#include "fe.h"
+
+static List symtab;
+
+Symbol
+newSymbol(name) char *name;
+{
+       Symbol s;
+
+       s = (Symbol) zalloc(sizeof(struct symbol));
+       assert(s);
+       s->name = name;
+       return s;
+}
+
+Symbol
+enter(name, new) char *name; int *new;
+{
+       List l;
+       Symbol s;
+
+       *new = 0;
+       for (l = symtab; l; l = l->next) {
+               s = (Symbol) l->x;
+               if (!strcmp(name, s->name)) {
+                       return s;
+               }
+       }
+       *new = 1;
+       s = newSymbol(name);
+       symtab = newList(s, symtab);
+       return s;
+}
diff --git a/utils/Burg/table.c b/utils/Burg/table.c
new file mode 100644 (file)
index 0000000..1de74f9
--- /dev/null
@@ -0,0 +1,552 @@
+char rcsid_table[] = "$Id$";
+
+#include "b.h"
+#include <string.h>
+#include <stdio.h>
+
+static void growIndex_Map ARGS((Index_Map *));
+static Relevant newRelevant ARGS((void));
+static Dimension newDimension ARGS((Operator, int));
+static void GT_1 ARGS((Table));
+static void GT_2_0 ARGS((Table));
+static void GT_2_1 ARGS((Table));
+static void growTransition ARGS((Table, int));
+static Item_Set restrict ARGS((Dimension, Item_Set));
+static void addHP_1 ARGS((Table, Item_Set));
+static void addHP_2_0 ARGS((Table, Item_Set));
+static void addHP_2_1 ARGS((Table, Item_Set));
+static void addHyperPlane ARGS((Table, int, Item_Set));
+
+static void
+growIndex_Map(r) Index_Map *r;
+{
+       Index_Map new;
+
+       new.max_size = r->max_size + STATES_INCR;
+       new.class = (Item_Set*) zalloc(new.max_size * sizeof(Item_Set));
+       assert(new.class);
+       memcpy(new.class, r->class, r->max_size * sizeof(Item_Set));
+       zfree(r->class);
+       *r = new;
+}
+
+static Relevant
+newRelevant()
+{
+       Relevant r = (Relevant) zalloc(max_nonterminal * sizeof(*r));
+       return r;
+}
+
+void
+addRelevant(r, nt) Relevant r; NonTerminalNum nt;
+{
+       int i;
+
+       for (i = 0; r[i]; i++) {
+               if (r[i] == nt) {
+                       break;
+               }
+       }
+       if (!r[i]) {
+               r[i] = nt;
+       }
+}
+
+static Dimension
+newDimension(op, index) Operator op; ArityNum index;
+{
+       Dimension d;
+       List pl;
+       Relevant r;
+
+       assert(op);
+       assert(index >= 0 && index < op->arity);
+       d = (Dimension) zalloc(sizeof(struct dimension));
+       assert(d);
+
+       r = d->relevant = newRelevant();
+       for (pl = rules; pl; pl = pl->next) {
+               Rule pr = (Rule) pl->x;
+               if (pr->pat->op == op) {
+                       addRelevant(r, pr->pat->children[index]->num);
+               }
+       }
+
+       d->index_map.max_size = STATES_INCR;
+       d->index_map.class = (Item_Set*) 
+                       zalloc(d->index_map.max_size * sizeof(Item_Set));
+       d->map = newMapping(DIM_MAP_SIZE);
+       d->max_size = TABLE_INCR;
+
+       return d;
+}
+
+Table
+newTable(op) Operator op;
+{
+       Table t;
+       int i, size;
+
+       assert(op);
+
+       t = (Table) zalloc(sizeof(struct table));
+       assert(t);
+
+       t->op = op;
+
+       for (i = 0; i < op->arity; i++) {
+               t->dimen[i] = newDimension(op, i);
+       }
+
+       size = 1;
+       for (i = 0; i < op->arity; i++) {
+               size *= t->dimen[i]->max_size;
+       }
+       t->transition = (Item_Set*) zalloc(size * sizeof(Item_Set));
+       t->relevant = newRelevant();
+       assert(t->transition);
+
+       return t;
+}
+
+static void
+GT_1(t) Table t;
+{
+       Item_Set        *ts;
+       ItemSetNum      oldsize = t->dimen[0]->max_size;
+       ItemSetNum      newsize = t->dimen[0]->max_size + TABLE_INCR;
+
+       t->dimen[0]->max_size = newsize;
+
+       ts = (Item_Set*) zalloc(newsize * sizeof(Item_Set));
+       assert(ts);
+       memcpy(ts, t->transition, oldsize * sizeof(Item_Set));
+       zfree(t->transition);
+       t->transition = ts;
+}
+
+static void
+GT_2_0(t) Table t;
+{
+       Item_Set        *ts;
+       ItemSetNum      oldsize = t->dimen[0]->max_size;
+       ItemSetNum      newsize = t->dimen[0]->max_size + TABLE_INCR;
+       int             size;
+
+       t->dimen[0]->max_size = newsize;
+
+       size = newsize * t->dimen[1]->max_size;
+
+       ts = (Item_Set*) zalloc(size * sizeof(Item_Set));
+       assert(ts);
+       memcpy(ts, t->transition, oldsize*t->dimen[1]->max_size * sizeof(Item_Set));
+       zfree(t->transition);
+       t->transition = ts;
+}
+
+static void
+GT_2_1(t) Table t;
+{
+       Item_Set        *ts;
+       ItemSetNum      oldsize = t->dimen[1]->max_size;
+       ItemSetNum      newsize = t->dimen[1]->max_size + TABLE_INCR;
+       int             size;
+       Item_Set        *from;
+       Item_Set        *to;
+       int             i1, i2;
+
+       t->dimen[1]->max_size = newsize;
+
+       size = newsize * t->dimen[0]->max_size;
+
+       ts = (Item_Set*) zalloc(size * sizeof(Item_Set));
+       assert(ts);
+
+       from = t->transition;
+       to = ts;
+       for (i1 = 0; i1 < t->dimen[0]->max_size; i1++) {
+               for (i2 = 0; i2 < oldsize; i2++) {
+                       to[i2] = from[i2];
+               }
+               to += newsize;
+               from += oldsize;
+       }
+       zfree(t->transition);
+       t->transition = ts;
+}
+
+static void
+growTransition(t, dim) Table t; ArityNum dim;
+{
+
+       assert(t);
+       assert(t->op);
+       assert(dim < t->op->arity);
+
+       switch (t->op->arity) {
+       default:
+               assert(0);
+               break;
+       case 1:
+               GT_1(t);
+               return;
+       case 2:
+               switch (dim) {
+               default:
+                       assert(0);
+                       break;
+               case 0:
+                       GT_2_0(t);
+                       return;
+               case 1:
+                       GT_2_1(t);
+                       return;
+               }
+       }
+}
+
+static Item_Set
+restrict(d, ts) Dimension d; Item_Set ts;
+{
+       DeltaCost       base;
+       Item_Set        r;
+       int found;
+       register Relevant r_ptr = d->relevant;
+       register Item *ts_current = ts->closed;
+       register Item *r_current;
+       register int i;
+       register int nt;
+
+       ZEROCOST(base);
+       found = 0;
+       r = newItem_Set(d->relevant);
+       r_current = r->virgin;
+       for (i = 0; (nt = r_ptr[i]) != 0; i++) {
+               if (ts_current[nt].rule) {
+                       r_current[nt].rule = &stub_rule;
+                       if (!found) {
+                               found = 1;
+                               ASSIGNCOST(base, ts_current[nt].delta);
+                       } else {
+                               if (LESSCOST(ts_current[nt].delta, base)) {
+                                       ASSIGNCOST(base, ts_current[nt].delta);
+                               }
+                       }
+               }
+       }
+
+       /* zero align */
+       for (i = 0; (nt = r_ptr[i]) != 0; i++) {
+               if (r_current[nt].rule) {
+                       ASSIGNCOST(r_current[nt].delta, ts_current[nt].delta);
+                       MINUSCOST(r_current[nt].delta, base);
+               }
+       }
+       assert(!r->closed);
+       r->representative = ts;
+       return r;
+}
+
+static void
+addHP_1(t, ts) Table t; Item_Set ts;
+{
+       List pl;
+       Item_Set e;
+       Item_Set tmp;
+       int new;
+
+       e = newItem_Set(t->relevant);
+       assert(e);
+       e->kids[0] = ts->representative;
+       for (pl = t->rules; pl; pl = pl->next) {
+               Rule p = (Rule) pl->x;
+               if (t->op == p->pat->op && ts->virgin[p->pat->children[0]->num].rule) {
+                       DeltaCost dc;
+                       ASSIGNCOST(dc, ts->virgin[p->pat->children[0]->num].delta);
+                       ADDCOST(dc, p->delta);
+                       if (!e->virgin[p->lhs->num].rule || LESSCOST(dc, e->virgin[p->lhs->num].delta)) {
+                               e->virgin[p->lhs->num].rule = p;
+                               ASSIGNCOST(e->virgin[p->lhs->num].delta, dc);
+                               e->op = t->op;
+                       }
+               }
+       }
+       trim(e);
+       zero(e);
+       tmp = encode(globalMap, e, &new);
+       assert(ts->num < t->dimen[0]->map->max_size);
+       t->transition[ts->num] = tmp;
+       if (new) {
+               closure(e);
+               addQ(globalQ, tmp);
+       } else {
+               freeItem_Set(e);
+       }
+}
+
+static void
+addHP_2_0(t, ts) Table t; Item_Set ts;
+{
+       List pl;
+       register Item_Set e;
+       Item_Set tmp;
+       int new;
+       int i2;
+
+       assert(t->dimen[1]->map->count <= t->dimen[1]->map->max_size);
+       for (i2 = 0; i2 < t->dimen[1]->map->count; i2++) {
+               e = newItem_Set(t->relevant);
+               assert(e);
+               e->kids[0] = ts->representative;
+               e->kids[1] = t->dimen[1]->map->set[i2]->representative;
+               for (pl = t->rules; pl; pl = pl->next) {
+                       register Rule p = (Rule) pl->x;
+
+                       if (t->op == p->pat->op 
+                                       && ts->virgin[p->pat->children[0]->num].rule
+                                       && t->dimen[1]->map->set[i2]->virgin[p->pat->children[1]->num].rule){
+                               DeltaCost dc;
+                               ASSIGNCOST(dc, p->delta);
+                               ADDCOST(dc, ts->virgin[p->pat->children[0]->num].delta);
+                               ADDCOST(dc, t->dimen[1]->map->set[i2]->virgin[p->pat->children[1]->num].delta);
+
+                               if (!e->virgin[p->lhs->num].rule || LESSCOST(dc, e->virgin[p->lhs->num].delta)) {
+                                       e->virgin[p->lhs->num].rule = p;
+                                       ASSIGNCOST(e->virgin[p->lhs->num].delta, dc);
+                                       e->op = t->op;
+                               }
+                       }
+               }
+               trim(e);
+               zero(e);
+               tmp = encode(globalMap, e, &new);
+               assert(ts->num < t->dimen[0]->map->max_size);
+               t->transition[ts->num * t->dimen[1]->max_size + i2] = tmp;
+               if (new) {
+                       closure(e);
+                       addQ(globalQ, tmp);
+               } else {
+                       freeItem_Set(e);
+               }
+       }
+}
+
+static void
+addHP_2_1(t, ts) Table t; Item_Set ts;
+{
+       List pl;
+       register Item_Set e;
+       Item_Set tmp;
+       int new;
+       int i1;
+
+       assert(t->dimen[0]->map->count <= t->dimen[0]->map->max_size);
+       for (i1 = 0; i1 < t->dimen[0]->map->count; i1++) {
+               e = newItem_Set(t->relevant);
+               assert(e);
+               e->kids[0] = t->dimen[0]->map->set[i1]->representative;
+               e->kids[1] = ts->representative;
+               for (pl = t->rules; pl; pl = pl->next) {
+                       register Rule p = (Rule) pl->x;
+
+                       if (t->op == p->pat->op 
+                                       && ts->virgin[p->pat->children[1]->num].rule
+                                       && t->dimen[0]->map->set[i1]->virgin[p->pat->children[0]->num].rule){
+                               DeltaCost dc;
+                               ASSIGNCOST(dc, p->delta );
+                               ADDCOST(dc, ts->virgin[p->pat->children[1]->num].delta);
+                               ADDCOST(dc, t->dimen[0]->map->set[i1]->virgin[p->pat->children[0]->num].delta);
+                               if (!e->virgin[p->lhs->num].rule || LESSCOST(dc, e->virgin[p->lhs->num].delta)) {
+                                       e->virgin[p->lhs->num].rule = p;
+                                       ASSIGNCOST(e->virgin[p->lhs->num].delta, dc);
+                                       e->op = t->op;
+                               }
+                       }
+               }
+               trim(e);
+               zero(e);
+               tmp = encode(globalMap, e, &new);
+               assert(ts->num < t->dimen[1]->map->max_size);
+               t->transition[i1 * t->dimen[1]->max_size + ts->num] = tmp;
+               if (new) {
+                       closure(e);
+                       addQ(globalQ, tmp);
+               } else {
+                       freeItem_Set(e);
+               }
+       }
+}
+
+static void
+addHyperPlane(t, i, ts) Table t; ArityNum i; Item_Set ts;
+{
+       switch (t->op->arity) {
+       default:
+               assert(0);
+               break;
+       case 1:
+               addHP_1(t, ts);
+               return;
+       case 2:
+               switch (i) {
+               default:
+                       assert(0);
+                       break;
+               case 0:
+                       addHP_2_0(t, ts);
+                       return;
+               case 1:
+                       addHP_2_1(t, ts);
+                       return;
+               }
+       }
+}
+
+void
+addToTable(t, ts) Table t; Item_Set ts;
+{
+       ArityNum i;
+
+       assert(t);
+       assert(ts);
+       assert(t->op);
+
+       for (i = 0; i < t->op->arity; i++) {
+               Item_Set r;
+               Item_Set tmp;
+               int new;
+
+               r = restrict(t->dimen[i], ts);
+               tmp = encode(t->dimen[i]->map, r, &new);
+               if (t->dimen[i]->index_map.max_size <= ts->num) {
+                       growIndex_Map(&t->dimen[i]->index_map);
+               }
+               assert(ts->num < t->dimen[i]->index_map.max_size);
+               t->dimen[i]->index_map.class[ts->num] = tmp;
+               if (new) {
+                       if (t->dimen[i]->max_size <= r->num) {
+                               growTransition(t, i);
+                       }
+                       addHyperPlane(t, i, r);
+               } else {
+                       freeItem_Set(r);
+               }
+       }
+}
+
+Item_Set *
+transLval(t, row, col) Table t; int row; int col;
+{
+       switch (t->op->arity) {
+       case 0:
+               assert(row == 0);
+               assert(col == 0);
+               return t->transition;
+       case 1:
+               assert(col == 0);
+               return t->transition + row;
+       case 2:
+               return t->transition + row * t->dimen[1]->max_size + col;
+       default:
+               assert(0);
+       }
+       return 0;
+}
+
+void
+dumpRelevant(r) Relevant r;
+{
+       for (; *r; r++) {
+               printf("%4d", *r);
+       }
+}
+
+void
+dumpIndex_Map(r) Index_Map *r;
+{
+       int i;
+
+       printf("BEGIN Index_Map: MaxSize (%d)\n", r->max_size);
+       for (i = 0; i < globalMap->count; i++) {
+               printf("\t#%d: -> %d\n", i, r->class[i]->num);
+       }
+       printf("END Index_Map:\n");
+}
+
+void
+dumpDimension(d) Dimension d;
+{
+       printf("BEGIN Dimension:\n");
+       printf("Relevant: ");
+       dumpRelevant(d->relevant);
+       printf("\n");
+       dumpIndex_Map(&d->index_map);
+       dumpMapping(d->map);
+       printf("MaxSize of dimension = %d\n", d->max_size);
+       printf("END Dimension\n");
+}
+
+void
+dumpTable(t, full) Table t; int full;
+{
+       int i;
+
+       if (!t) {
+               printf("NO Table yet.\n");
+               return;
+       }
+       printf("BEGIN Table:\n");
+       if (full) {
+               dumpOperator(t->op, 0);
+       }
+       for (i = 0; i < t->op->arity; i++) {
+               printf("BEGIN dimension(%d)\n", i);
+               dumpDimension(t->dimen[i]);
+               printf("END dimension(%d)\n", i);
+       }
+       dumpTransition(t);
+       printf("END Table:\n");
+}
+
+void
+dumpTransition(t) Table t;
+{
+       int i,j;
+
+       switch (t->op->arity) {
+       case 0:
+               printf("{ %d }", t->transition[0]->num);
+               break;
+       case 1:
+               printf("{");
+               for (i = 0; i < t->dimen[0]->map->count; i++) {
+                       if (i > 0) {
+                               printf(",");
+                       }
+                       printf("%5d", t->transition[i]->num);
+               }
+               printf("}");
+               break;
+       case 2:
+               printf("{");
+               for (i = 0; i < t->dimen[0]->map->count; i++) {
+                       if (i > 0) {
+                               printf(",");
+                       }
+                       printf("\n");
+                       printf("{");
+                       for (j = 0; j < t->dimen[1]->map->count; j++) {
+                               Item_Set *ts = transLval(t, i, j);
+                               if (j > 0) {
+                                       printf(",");
+                               }
+                               printf("%5d", (*ts)->num);
+                       }
+                       printf("}");
+               }
+               printf("\n}\n");
+               break;
+       default:
+               assert(0);
+       }
+}
diff --git a/utils/Burg/trim.c b/utils/Burg/trim.c
new file mode 100644 (file)
index 0000000..05ee2d0
--- /dev/null
@@ -0,0 +1,412 @@
+char rcsid_trim[] = "$Id$";
+
+#include <stdio.h>
+#include "b.h"
+#include "fe.h"
+
+Relation *allpairs;
+
+int trimflag = 0;
+int debugTrim = 0;
+
+static void siblings ARGS((int, int));
+static void findAllNexts ARGS((void));
+static Relation *newAllPairs ARGS((void));
+
+static void
+siblings(i, j) int i; int j;
+{
+       int k;
+       List pl;
+       DeltaCost Max;
+       int foundmax;
+
+       allpairs[i][j].sibComputed = 1;
+
+       if (i == 1) {
+               return; /* never trim start symbol */
+       }
+       if (i==j) {
+               return;
+       }
+
+       ZEROCOST(Max);
+       foundmax = 0;
+
+       for (k = 1; k < max_nonterminal; k++) {
+               DeltaCost tmp;
+
+               if (k==i || k==j) {
+                       continue;
+               }
+               if (!allpairs[k][i].rule) {
+                       continue;
+               }
+               if (!allpairs[k][j].rule) {
+                       return;
+               }
+               ASSIGNCOST(tmp, allpairs[k][j].chain);
+               MINUSCOST(tmp, allpairs[k][i].chain);
+               if (foundmax) {
+                       if (LESSCOST(Max, tmp)) {
+                               ASSIGNCOST(Max, tmp);
+                       }
+               } else {
+                       foundmax = 1;
+                       ASSIGNCOST(Max, tmp);
+               }
+       }
+
+       for (pl = rules; pl; pl = pl->next) {
+               Rule p = (Rule) pl->x;
+               Operator op = p->pat->op;
+               List oprule;
+               DeltaCost Min;
+               int foundmin;
+               
+               if (!op) {
+                       continue;
+               }
+               switch (op->arity) {
+               case 0:
+                       continue;
+               case 1:
+                       if (!allpairs[p->pat->children[0]->num ][ i].rule) {
+                               continue;
+                       }
+                       foundmin = 0;
+                       for (oprule = op->table->rules; oprule; oprule = oprule->next) {
+                               Rule s = (Rule) oprule->x;
+                               DeltaPtr Cx;
+                               DeltaPtr Csj;
+                               DeltaPtr Cpi;
+                               DeltaCost tmp;
+
+                               if (!allpairs[p->lhs->num ][ s->lhs->num].rule
+                                || !allpairs[s->pat->children[0]->num ][ j].rule) {
+                                       continue;
+                               }
+                               Cx = allpairs[p->lhs->num ][ s->lhs->num].chain;
+                               Csj= allpairs[s->pat->children[0]->num ][ j].chain;
+                               Cpi= allpairs[p->pat->children[0]->num ][ i].chain;
+                               ASSIGNCOST(tmp, Cx);
+                               ADDCOST(tmp, s->delta);
+                               ADDCOST(tmp, Csj);
+                               MINUSCOST(tmp, Cpi);
+                               MINUSCOST(tmp, p->delta);
+                               if (foundmin) {
+                                       if (LESSCOST(tmp, Min)) {
+                                               ASSIGNCOST(Min, tmp);
+                                       }
+                               } else {
+                                       foundmin = 1;
+                                       ASSIGNCOST(Min, tmp);
+                               }
+                       }
+                       if (!foundmin) {
+                               return;
+                       }
+                       if (foundmax) {
+                               if (LESSCOST(Max, Min)) {
+                                       ASSIGNCOST(Max, Min);
+                               }
+                       } else {
+                               foundmax = 1;
+                               ASSIGNCOST(Max, Min);
+                       }
+                       break;
+               case 2:
+               /* do first dimension */
+               if (allpairs[p->pat->children[0]->num ][ i].rule) {
+                       foundmin = 0;
+                       for (oprule = op->table->rules; oprule; oprule = oprule->next) {
+                               Rule s = (Rule) oprule->x;
+                               DeltaPtr Cx;
+                               DeltaPtr Cb;
+                               DeltaPtr Csj;
+                               DeltaPtr Cpi;
+                               DeltaCost tmp;
+
+                               if (allpairs[p->lhs->num ][ s->lhs->num].rule
+                                && allpairs[s->pat->children[0]->num ][ j].rule
+                                && allpairs[s->pat->children[1]->num ][ p->pat->children[1]->num].rule) {
+                                       Cx = allpairs[p->lhs->num ][ s->lhs->num].chain;
+                                       Csj= allpairs[s->pat->children[0]->num ][ j].chain;
+                                       Cpi= allpairs[p->pat->children[0]->num ][ i].chain;
+                                       Cb = allpairs[s->pat->children[1]->num ][ p->pat->children[1]->num].chain;
+                                       ASSIGNCOST(tmp, Cx);
+                                       ADDCOST(tmp, s->delta);
+                                       ADDCOST(tmp, Csj);
+                                       ADDCOST(tmp, Cb);
+                                       MINUSCOST(tmp, Cpi);
+                                       MINUSCOST(tmp, p->delta);
+                                       if (foundmin) {
+                                               if (LESSCOST(tmp, Min)) {
+                                                       ASSIGNCOST(Min, tmp);
+                                               }
+                                       } else {
+                                               foundmin = 1;
+                                               ASSIGNCOST(Min, tmp);
+                                       }
+                               }
+                       }
+                       if (!foundmin) {
+                               return;
+                       }
+                       if (foundmax) {
+                               if (LESSCOST(Max, Min)) {
+                                       ASSIGNCOST(Max, Min);
+                               }
+                       } else {
+                               foundmax = 1;
+                               ASSIGNCOST(Max, Min);
+                       }
+               }
+               /* do second dimension */
+               if (allpairs[p->pat->children[1]->num ][ i].rule) {
+                       foundmin = 0;
+                       for (oprule = op->table->rules; oprule; oprule = oprule->next) {
+                               Rule s = (Rule) oprule->x;
+                               DeltaPtr Cx;
+                               DeltaPtr Cb;
+                               DeltaPtr Csj;
+                               DeltaPtr Cpi;
+                               DeltaCost tmp;
+
+                               if (allpairs[p->lhs->num ][ s->lhs->num].rule
+                                && allpairs[s->pat->children[1]->num ][ j].rule
+                                && allpairs[s->pat->children[0]->num ][ p->pat->children[0]->num].rule) {
+                                       Cx = allpairs[p->lhs->num ][ s->lhs->num].chain;
+                                       Csj= allpairs[s->pat->children[1]->num ][ j].chain;
+                                       Cpi= allpairs[p->pat->children[1]->num ][ i].chain;
+                                       Cb = allpairs[s->pat->children[0]->num ][ p->pat->children[0]->num].chain;
+                                       ASSIGNCOST(tmp, Cx);
+                                       ADDCOST(tmp, s->delta);
+                                       ADDCOST(tmp, Csj);
+                                       ADDCOST(tmp, Cb);
+                                       MINUSCOST(tmp, Cpi);
+                                       MINUSCOST(tmp, p->delta);
+                                       if (foundmin) {
+                                               if (LESSCOST(tmp, Min)) {
+                                                       ASSIGNCOST(Min, tmp);
+                                               }
+                                       } else {
+                                               foundmin = 1;
+                                               ASSIGNCOST(Min, tmp);
+                                       }
+                               }
+                       }
+                       if (!foundmin) {
+                               return;
+                       }
+                       if (foundmax) {
+                               if (LESSCOST(Max, Min)) {
+                                       ASSIGNCOST(Max, Min);
+                               }
+                       } else {
+                               foundmax = 1;
+                               ASSIGNCOST(Max, Min);
+                       }
+               }
+               break;
+               default:
+                       assert(0);
+               }
+       }
+       allpairs[i ][ j].sibFlag = foundmax;
+       ASSIGNCOST(allpairs[i ][ j].sibling, Max);
+}
+
+static void
+findAllNexts()
+{
+       int i,j;
+       int last;
+
+       for (i = 1; i < max_nonterminal; i++) {
+               last = 0;
+               for (j = 1; j < max_nonterminal; j++) {
+                       if (allpairs[i ][j].rule) {
+                               allpairs[i ][ last].nextchain = j;
+                               last = j;
+                       }
+               }
+       }
+       /*
+       for (i = 1; i < max_nonterminal; i++) {
+               last = 0;
+               for (j = 1; j < max_nonterminal; j++) {
+                       if (allpairs[i ][j].sibFlag) {
+                               allpairs[i ][ last].nextsibling = j;
+                               last = j;
+                       }
+               }
+       }
+       */
+}
+
+static Relation *
+newAllPairs()
+{
+       int i;
+       Relation *rv;
+
+       rv = (Relation*) zalloc(max_nonterminal * sizeof(Relation));
+       for (i = 0; i < max_nonterminal; i++) {
+               rv[i] = (Relation) zalloc(max_nonterminal * sizeof(struct relation));
+       }
+       return rv;
+}
+
+void
+findAllPairs()
+{
+       List pl;
+       int changes;
+       int j;
+
+       allpairs = newAllPairs();
+       for (pl = chainrules; pl; pl = pl->next) {
+               Rule p = (Rule) pl->x;
+               NonTerminalNum rhs = p->pat->children[0]->num;
+               NonTerminalNum lhs = p->lhs->num;
+               Relation r = &allpairs[lhs ][ rhs];
+
+               if (LESSCOST(p->delta, r->chain)) {
+                       ASSIGNCOST(r->chain, p->delta);
+                       r->rule = p;
+               }
+       }
+       for (j = 1; j < max_nonterminal; j++) {
+               Relation r = &allpairs[j ][ j];
+               ZEROCOST(r->chain);
+               r->rule = &stub_rule;
+       }
+       changes = 1;
+       while (changes) {
+               changes = 0;
+               for (pl = chainrules; pl; pl = pl->next) {
+                       Rule p = (Rule) pl->x;
+                       NonTerminalNum rhs = p->pat->children[0]->num;
+                       NonTerminalNum lhs = p->lhs->num;
+                       int i;
+
+                       for (i = 1; i < max_nonterminal; i++) {
+                               Relation r = &allpairs[rhs ][ i];
+                               Relation s = &allpairs[lhs ][ i];
+                               DeltaCost dc;
+                               if (!r->rule) {
+                                       continue;
+                               }
+                               ASSIGNCOST(dc, p->delta);
+                               ADDCOST(dc, r->chain);
+                               if (!s->rule || LESSCOST(dc, s->chain)) {
+                                       s->rule = p;
+                                       ASSIGNCOST(s->chain, dc);
+                                       changes = 1;
+                               }
+                       }
+               }
+       }
+       findAllNexts();
+}
+
+void
+trim(t) Item_Set t;
+{
+       int m,n;
+       static short *vec = 0;
+       int last;
+
+       assert(!t->closed);
+       debug(debugTrim, printf("Begin Trim\n"));
+       debug(debugTrim, dumpItem_Set(t));
+
+       last = 0;
+       if (!vec) {
+               vec = (short*) zalloc(max_nonterminal * sizeof(*vec));
+       }
+       for (m = 1; m < max_nonterminal; m++) {
+               if (t->virgin[m].rule) {
+                       vec[last++] = m;
+               }
+       }
+       for (m = 0; m < last; m++) {
+               DeltaCost tmp;
+               int j;
+               int i;
+
+               i = vec[m];
+
+               for (j = allpairs[i ][ 0].nextchain; j; j = allpairs[i ][ j].nextchain) {
+
+                       if (i == j) {
+                               continue;
+                       }
+                       if (!t->virgin[j].rule) {
+                               continue;
+                       }
+                       ASSIGNCOST(tmp, t->virgin[j].delta);
+                       ADDCOST(tmp, allpairs[i ][ j].chain);
+                       if (!LESSCOST(t->virgin[i].delta, tmp)) {
+                               t->virgin[i].rule = 0;
+                               ZEROCOST(t->virgin[i].delta);
+                               debug(debugTrim, printf("Trimmed Chain (%d,%d)\n", i,j));
+                               goto outer;
+                       }
+                       
+               }
+               if (!trimflag) {
+                       continue;
+               }
+               for (n = 0; n < last; n++) {
+                       j = vec[n];
+                       if (i == j) {
+                               continue;
+                       }
+
+                       if (!t->virgin[j].rule) {
+                               continue;
+                       }
+
+                       if (!allpairs[i][j].sibComputed) {
+                               siblings(i,j);
+                       }
+                       if (!allpairs[i][j].sibFlag) {
+                               continue;
+                       }
+                       ASSIGNCOST(tmp, t->virgin[j].delta);
+                       ADDCOST(tmp, allpairs[i ][ j].sibling);
+                       if (!LESSCOST(t->virgin[i].delta, tmp)) {
+                               t->virgin[i].rule = 0;
+                               ZEROCOST(t->virgin[i].delta);
+                               goto outer;
+                       }
+               }
+
+               outer: ;
+       }
+
+       debug(debugTrim, dumpItem_Set(t));
+       debug(debugTrim, printf("End Trim\n"));
+}
+
+void
+dumpRelation(r) Relation r;
+{
+       printf("{ %d %ld %d %ld }", r->rule->erulenum, (long) r->chain, r->sibFlag, (long) r->sibling);
+}
+
+void
+dumpAllPairs()
+{
+       int i,j;
+
+       printf("Dumping AllPairs\n");
+       for (i = 1; i < max_nonterminal; i++) {
+               for (j = 1; j < max_nonterminal; j++) {
+                       dumpRelation(&allpairs[i ][j]);
+               }
+               printf("\n");
+       }
+}
diff --git a/utils/Burg/zalloc.c b/utils/Burg/zalloc.c
new file mode 100644 (file)
index 0000000..bd50217
--- /dev/null
@@ -0,0 +1,35 @@
+char rcsid_zalloc[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+
+extern void exit ARGS((int));
+extern void free ARGS((void *));
+extern void *malloc ARGS((unsigned));
+
+int
+fatal(name, line) char *name; int line;
+{
+       fprintf(stderr, "assertion failed: file %s, line %d\n", name, line);
+       exit(1);
+       return 0;
+}
+
+void *
+zalloc(size) unsigned int size;
+{
+       void *t = (void *) malloc(size);
+       if (!t) {
+               fprintf(stderr, "Malloc failed---PROGRAM ABORTED\n");
+               exit(1);
+       }
+       memset(t, 0, size);
+       return t;
+}
+
+void
+zfree(p) void *p;
+{
+       free(p);
+}