From 633a5b1aacb135957b20e5f11e779ea23ccb9619 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 17 Sep 2002 23:03:30 +0000 Subject: [PATCH] Initial checkin of burg files git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@3785 91177308-0d34-0410-b5e6-96231b3b80d8 --- support/tools/Burg/COPYRIGHT | 13 + support/tools/Burg/LOG_CHANGES | 2 + support/tools/Burg/Makefile | 84 +++ support/tools/Burg/README | 14 + support/tools/Burg/b.h | 311 +++++++++ support/tools/Burg/be.c | 1052 ++++++++++++++++++++++++++++++ support/tools/Burg/burg.shar.gz | Bin 0 -> 38843 bytes support/tools/Burg/burs.c | 71 ++ support/tools/Burg/closure.c | 95 +++ support/tools/Burg/delta.c | 143 ++++ support/tools/Burg/fe.c | 403 ++++++++++++ support/tools/Burg/fe.h | 127 ++++ support/tools/Burg/gram.y | 90 +++ support/tools/Burg/item.c | 133 ++++ support/tools/Burg/lex.c | 260 ++++++++ support/tools/Burg/list.c | 75 +++ support/tools/Burg/main.c | 182 ++++++ support/tools/Burg/map.c | 135 ++++ support/tools/Burg/nonterminal.c | 49 ++ support/tools/Burg/operator.c | 48 ++ support/tools/Burg/pattern.c | 38 ++ support/tools/Burg/plank.c | 920 ++++++++++++++++++++++++++ support/tools/Burg/queue.c | 64 ++ support/tools/Burg/rule.c | 49 ++ support/tools/Burg/sample.gr | 150 +++++ support/tools/Burg/string.c | 65 ++ support/tools/Burg/symtab.c | 38 ++ support/tools/Burg/table.c | 552 ++++++++++++++++ support/tools/Burg/trim.c | 412 ++++++++++++ support/tools/Burg/zalloc.c | 35 + utils/Burg/COPYRIGHT | 13 + utils/Burg/LOG_CHANGES | 2 + utils/Burg/Makefile | 84 +++ utils/Burg/README | 14 + utils/Burg/b.h | 311 +++++++++ utils/Burg/be.c | 1052 ++++++++++++++++++++++++++++++ utils/Burg/burg.shar.gz | Bin 0 -> 38843 bytes utils/Burg/burs.c | 71 ++ utils/Burg/closure.c | 95 +++ utils/Burg/delta.c | 143 ++++ utils/Burg/fe.c | 403 ++++++++++++ utils/Burg/fe.h | 127 ++++ utils/Burg/gram.y | 90 +++ utils/Burg/item.c | 133 ++++ utils/Burg/lex.c | 260 ++++++++ utils/Burg/list.c | 75 +++ utils/Burg/main.c | 182 ++++++ utils/Burg/map.c | 135 ++++ utils/Burg/nonterminal.c | 49 ++ utils/Burg/operator.c | 48 ++ utils/Burg/pattern.c | 38 ++ utils/Burg/plank.c | 920 ++++++++++++++++++++++++++ utils/Burg/queue.c | 64 ++ utils/Burg/rule.c | 49 ++ utils/Burg/sample.gr | 150 +++++ utils/Burg/string.c | 65 ++ utils/Burg/symtab.c | 38 ++ utils/Burg/table.c | 552 ++++++++++++++++ utils/Burg/trim.c | 412 ++++++++++++ utils/Burg/zalloc.c | 35 + 60 files changed, 11220 insertions(+) create mode 100644 support/tools/Burg/COPYRIGHT create mode 100644 support/tools/Burg/LOG_CHANGES create mode 100644 support/tools/Burg/Makefile create mode 100644 support/tools/Burg/README create mode 100644 support/tools/Burg/b.h create mode 100644 support/tools/Burg/be.c create mode 100644 support/tools/Burg/burg.shar.gz create mode 100644 support/tools/Burg/burs.c create mode 100644 support/tools/Burg/closure.c create mode 100644 support/tools/Burg/delta.c create mode 100644 support/tools/Burg/fe.c create mode 100644 support/tools/Burg/fe.h create mode 100644 support/tools/Burg/gram.y create mode 100644 support/tools/Burg/item.c create mode 100644 support/tools/Burg/lex.c create mode 100644 support/tools/Burg/list.c create mode 100644 support/tools/Burg/main.c create mode 100644 support/tools/Burg/map.c create mode 100644 support/tools/Burg/nonterminal.c create mode 100644 support/tools/Burg/operator.c create mode 100644 support/tools/Burg/pattern.c create mode 100644 support/tools/Burg/plank.c create mode 100644 support/tools/Burg/queue.c create mode 100644 support/tools/Burg/rule.c create mode 100644 support/tools/Burg/sample.gr create mode 100644 support/tools/Burg/string.c create mode 100644 support/tools/Burg/symtab.c create mode 100644 support/tools/Burg/table.c create mode 100644 support/tools/Burg/trim.c create mode 100644 support/tools/Burg/zalloc.c create mode 100644 utils/Burg/COPYRIGHT create mode 100644 utils/Burg/LOG_CHANGES create mode 100644 utils/Burg/Makefile create mode 100644 utils/Burg/README create mode 100644 utils/Burg/b.h create mode 100644 utils/Burg/be.c create mode 100644 utils/Burg/burg.shar.gz create mode 100644 utils/Burg/burs.c create mode 100644 utils/Burg/closure.c create mode 100644 utils/Burg/delta.c create mode 100644 utils/Burg/fe.c create mode 100644 utils/Burg/fe.h create mode 100644 utils/Burg/gram.y create mode 100644 utils/Burg/item.c create mode 100644 utils/Burg/lex.c create mode 100644 utils/Burg/list.c create mode 100644 utils/Burg/main.c create mode 100644 utils/Burg/map.c create mode 100644 utils/Burg/nonterminal.c create mode 100644 utils/Burg/operator.c create mode 100644 utils/Burg/pattern.c create mode 100644 utils/Burg/plank.c create mode 100644 utils/Burg/queue.c create mode 100644 utils/Burg/rule.c create mode 100644 utils/Burg/sample.gr create mode 100644 utils/Burg/string.c create mode 100644 utils/Burg/symtab.c create mode 100644 utils/Burg/table.c create mode 100644 utils/Burg/trim.c create mode 100644 utils/Burg/zalloc.c diff --git a/support/tools/Burg/COPYRIGHT b/support/tools/Burg/COPYRIGHT new file mode 100644 index 00000000000..1de0aad6f2f --- /dev/null +++ b/support/tools/Burg/COPYRIGHT @@ -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 index 00000000000..a7ee3430ae5 --- /dev/null +++ b/support/tools/Burg/LOG_CHANGES @@ -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 index 00000000000..226210d6ca4 --- /dev/null +++ b/support/tools/Burg/Makefile @@ -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.c && cc $(CFLAGS) -o sample sample.c && ./sample + ./burg -I sample.gr >tmp && cmp tmp sample.c + ./burg -I tmp && cmp tmp sample.c + ./burg -I -= tmp && cmp tmp sample.c diff --git a/support/tools/Burg/README b/support/tools/Burg/README new file mode 100644 index 00000000000..bc26405727e --- /dev/null +++ b/support/tools/Burg/README @@ -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 index 00000000000..f1b33edd943 --- /dev/null +++ b/support/tools/Burg/b.h @@ -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 index 00000000000..e7feab8d5dd --- /dev/null +++ b/support/tools/Burg/be.c @@ -0,0 +1,1052 @@ +char rcsid_be[] = "$Id$"; + +#include +#include +#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 index 0000000000000000000000000000000000000000..173bbfde9f6b403435e6b0bef42493d5d6b5b6bf GIT binary patch literal 38843 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 z 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 z zybClXr1GE>?=CRGvEU<7Mes*(2N7XBcNjN?%;iHibK;}ooBTuJ)i~3yf|VD+i7{Xz z8uHKr%5`v^x;l9U9)raeBGSkckC1qm0)m#6REE*2S_{DNDvmS1yDB=+6+`Cm=u2qg zrq_AN5hK^ht;iK{5CE&>OL%7KI12C>i(B8n2-CV*mtl_%NhUx;L1I6L8_2Y22|^!+$qED?f;qtd>C)GK)?j277mi2fZn+WR z_8Fu#5X&RQO&i;zH^bPBD>wPXb3FN!aIOP-zrHxxfhoEcJ!q}K>f{rLL%S9h_GPYM z@VZpz)-(uplqJ;dja^wy$qC@BJ3OUZCu+vXs@5Jm7`i6x5Xr_xB=^;ZuOQLGgsy5R z+hSrh`lg22OsSBaQgmwh!BQ6%2Ks_tBoD0565X8@c*IRc$5?odd@JlH6BewjXPcqR zODvWWxIZu}qgJg6*}_P#UFUur76KsCYxwl%Gdv-w%Ufggvt`r@UwVQoX80?nc)2;& z=ijx}t8Z$mn*>7MUPm|vkOYeiT%AB&Vq?I;I1WujI$$Cl#E5j@ zM_^iK*g&;_M&BWfH*VnGF(`5yKGmZ>2z{#IP|2!UmhZ19Tua!`z_3co#{A8?r6dnv zWys>fA|F%{g2KuLbk1hasG>&$?Al^65lTX_DxvP-)sDr<`G-!KR;{EYLE&@)+hFDb zH1(O2S3s7WDCLfU7h5r_u9T$lX^{4kMv?_ zRE~tpkB2x7I1|#)64KDI(GNl)!^6(f6Z%zC>ME6=-`d*h?D)f4fsl#~cyj3PNKFFQ zKZTy61R;o}*IS9Os3m!1IfY_AUd?ig9+b4DiU+0a!X4k~k6ffy`#tm5oShlj?Bp&$ zt5b^m#K~juOD0r*REQ6NiE0GKsmlQK7z&~aVhVdHmX{MaE~71ZNcthro1)G?HYal2 zt%qD%e6Jq%VX1KHu^utY`t)#x(4~hr$18Q}u}v;?>ro|>gZkapW~E<`1GUPthf68n z9#icfk+yc_t-g5&?}c~XIkeRD=M#555nt3(C{cNJPlm|=PrB1?U-G%a3QCJ9X7R18 z-NFU;EUe-3KIy{b0kUWgS95O6xXG&Kk&M-K_c1qYROM9)o3+GVcY)wY&KCrS3sZ_S z8Na@I$hx;$pVarity == 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 index 00000000000..70e16264ebb --- /dev/null +++ b/support/tools/Burg/closure.c @@ -0,0 +1,95 @@ +char rcsid_closure[] = "$Id$"; + +#include +#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 index 00000000000..d79654910fc --- /dev/null +++ b/support/tools/Burg/delta.c @@ -0,0 +1,143 @@ +char rcsid_delta[] = "$Id$"; + +#include +#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 index 00000000000..36b373dd650 --- /dev/null +++ b/support/tools/Burg/fe.c @@ -0,0 +1,403 @@ +char rcsid_fe[] = "$Id$"; + +#include +#include +#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 index 00000000000..5cef79bbe14 --- /dev/null +++ b/support/tools/Burg/fe.h @@ -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 index 00000000000..f6f16faf8ef --- /dev/null +++ b/support/tools/Burg/gram.y @@ -0,0 +1,90 @@ +%{ +char rcsid_gram[] = "$Id$"; + +#include +#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 ID +%token INT + +%type decl +%type binding +%type cost costtail +%type rule +%type pattern +%type 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 index 00000000000..4a9f4a320b6 --- /dev/null +++ b/support/tools/Burg/item.c @@ -0,0 +1,133 @@ +char rcsid_item[] = "$Id$"; + +#include "b.h" +#include +#include +#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 index 00000000000..3d6c5af5c48 --- /dev/null +++ b/support/tools/Burg/lex.c @@ -0,0 +1,260 @@ +char rcsid_lex[] = "$Id$"; + +#include +#include +#include +#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 index 00000000000..d3eefa27d09 --- /dev/null +++ b/support/tools/Burg/list.c @@ -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 index 00000000000..5c13698f1cb --- /dev/null +++ b/support/tools/Burg/main.c @@ -0,0 +1,182 @@ +char rcsid_main[] = "$Id$"; + +#include +#include +#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 index 00000000000..6c3c15454cd --- /dev/null +++ b/support/tools/Burg/map.c @@ -0,0 +1,135 @@ +char rcsid_map[] = "$Id$"; + +#include +#include +#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 index 00000000000..af88dd61ea9 --- /dev/null +++ b/support/tools/Burg/nonterminal.c @@ -0,0 +1,49 @@ +char rcsid_nonterminal[] = "$Id$"; + +#include "b.h" +#include + +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 index 00000000000..a6df9e304df --- /dev/null +++ b/support/tools/Burg/operator.c @@ -0,0 +1,48 @@ +char rcsid_operator[] = "$Id$"; + +#include "b.h" +#include + +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 index 00000000000..472aca579d0 --- /dev/null +++ b/support/tools/Burg/pattern.c @@ -0,0 +1,38 @@ +char rcsid_pattern[] = "$Id$"; + +#include +#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 index 00000000000..053304eafc3 --- /dev/null +++ b/support/tools/Burg/plank.c @@ -0,0 +1,920 @@ +char rcsid_plank[] = "$Id$"; + +#include +#include +#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 index 00000000000..76e5ea9b57b --- /dev/null +++ b/support/tools/Burg/queue.c @@ -0,0 +1,64 @@ +char rcsid_queue[] = "$Id$"; + +#include "b.h" +#include + +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 index 00000000000..ee5c89e8933 --- /dev/null +++ b/support/tools/Burg/rule.c @@ -0,0 +1,49 @@ +char rcsid_rule[] = "$Id$"; + +#include "b.h" +#include + +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 index 00000000000..e1f7283b6d6 --- /dev/null +++ b/support/tools/Burg/sample.gr @@ -0,0 +1,150 @@ +%{ +#include + +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 index 00000000000..9b69c3045ff --- /dev/null +++ b/support/tools/Burg/string.c @@ -0,0 +1,65 @@ +char rcsid_string[] = "$Id$"; + +#include +#include +#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 index 00000000000..3ecab2fc5ff --- /dev/null +++ b/support/tools/Burg/symtab.c @@ -0,0 +1,38 @@ +char rcsid_symtab[] = "$Id$"; + +#include +#include +#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 index 00000000000..1de74f9a107 --- /dev/null +++ b/support/tools/Burg/table.c @@ -0,0 +1,552 @@ +char rcsid_table[] = "$Id$"; + +#include "b.h" +#include +#include + +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 index 00000000000..05ee2d0f646 --- /dev/null +++ b/support/tools/Burg/trim.c @@ -0,0 +1,412 @@ +char rcsid_trim[] = "$Id$"; + +#include +#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 index 00000000000..bd50217308e --- /dev/null +++ b/support/tools/Burg/zalloc.c @@ -0,0 +1,35 @@ +char rcsid_zalloc[] = "$Id$"; + +#include +#include +#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 index 00000000000..1de0aad6f2f --- /dev/null +++ b/utils/Burg/COPYRIGHT @@ -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 index 00000000000..a7ee3430ae5 --- /dev/null +++ b/utils/Burg/LOG_CHANGES @@ -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 index 00000000000..226210d6ca4 --- /dev/null +++ b/utils/Burg/Makefile @@ -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.c && cc $(CFLAGS) -o sample sample.c && ./sample + ./burg -I sample.gr >tmp && cmp tmp sample.c + ./burg -I tmp && cmp tmp sample.c + ./burg -I -= tmp && cmp tmp sample.c diff --git a/utils/Burg/README b/utils/Burg/README new file mode 100644 index 00000000000..bc26405727e --- /dev/null +++ b/utils/Burg/README @@ -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 index 00000000000..f1b33edd943 --- /dev/null +++ b/utils/Burg/b.h @@ -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 index 00000000000..e7feab8d5dd --- /dev/null +++ b/utils/Burg/be.c @@ -0,0 +1,1052 @@ +char rcsid_be[] = "$Id$"; + +#include +#include +#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 index 0000000000000000000000000000000000000000..173bbfde9f6b403435e6b0bef42493d5d6b5b6bf GIT binary patch literal 38843 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 z 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 z zybClXr1GE>?=CRGvEU<7Mes*(2N7XBcNjN?%;iHibK;}ooBTuJ)i~3yf|VD+i7{Xz z8uHKr%5`v^x;l9U9)raeBGSkckC1qm0)m#6REE*2S_{DNDvmS1yDB=+6+`Cm=u2qg zrq_AN5hK^ht;iK{5CE&>OL%7KI12C>i(B8n2-CV*mtl_%NhUx;L1I6L8_2Y22|^!+$qED?f;qtd>C)GK)?j277mi2fZn+WR z_8Fu#5X&RQO&i;zH^bPBD>wPXb3FN!aIOP-zrHxxfhoEcJ!q}K>f{rLL%S9h_GPYM z@VZpz)-(uplqJ;dja^wy$qC@BJ3OUZCu+vXs@5Jm7`i6x5Xr_xB=^;ZuOQLGgsy5R z+hSrh`lg22OsSBaQgmwh!BQ6%2Ks_tBoD0565X8@c*IRc$5?odd@JlH6BewjXPcqR zODvWWxIZu}qgJg6*}_P#UFUur76KsCYxwl%Gdv-w%Ufggvt`r@UwVQoX80?nc)2;& z=ijx}t8Z$mn*>7MUPm|vkOYeiT%AB&Vq?I;I1WujI$$Cl#E5j@ zM_^iK*g&;_M&BWfH*VnGF(`5yKGmZ>2z{#IP|2!UmhZ19Tua!`z_3co#{A8?r6dnv zWys>fA|F%{g2KuLbk1hasG>&$?Al^65lTX_DxvP-)sDr<`G-!KR;{EYLE&@)+hFDb zH1(O2S3s7WDCLfU7h5r_u9T$lX^{4kMv?_ zRE~tpkB2x7I1|#)64KDI(GNl)!^6(f6Z%zC>ME6=-`d*h?D)f4fsl#~cyj3PNKFFQ zKZTy61R;o}*IS9Os3m!1IfY_AUd?ig9+b4DiU+0a!X4k~k6ffy`#tm5oShlj?Bp&$ zt5b^m#K~juOD0r*REQ6NiE0GKsmlQK7z&~aVhVdHmX{MaE~71ZNcthro1)G?HYal2 zt%qD%e6Jq%VX1KHu^utY`t)#x(4~hr$18Q}u}v;?>ro|>gZkapW~E<`1GUPthf68n z9#icfk+yc_t-g5&?}c~XIkeRD=M#555nt3(C{cNJPlm|=PrB1?U-G%a3QCJ9X7R18 z-NFU;EUe-3KIy{b0kUWgS95O6xXG&Kk&M-K_c1qYROM9)o3+GVcY)wY&KCrS3sZ_S z8Na@I$hx;$pVarity == 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 index 00000000000..70e16264ebb --- /dev/null +++ b/utils/Burg/closure.c @@ -0,0 +1,95 @@ +char rcsid_closure[] = "$Id$"; + +#include +#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 index 00000000000..d79654910fc --- /dev/null +++ b/utils/Burg/delta.c @@ -0,0 +1,143 @@ +char rcsid_delta[] = "$Id$"; + +#include +#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 index 00000000000..36b373dd650 --- /dev/null +++ b/utils/Burg/fe.c @@ -0,0 +1,403 @@ +char rcsid_fe[] = "$Id$"; + +#include +#include +#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 index 00000000000..5cef79bbe14 --- /dev/null +++ b/utils/Burg/fe.h @@ -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 index 00000000000..f6f16faf8ef --- /dev/null +++ b/utils/Burg/gram.y @@ -0,0 +1,90 @@ +%{ +char rcsid_gram[] = "$Id$"; + +#include +#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 ID +%token INT + +%type decl +%type binding +%type cost costtail +%type rule +%type pattern +%type 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 index 00000000000..4a9f4a320b6 --- /dev/null +++ b/utils/Burg/item.c @@ -0,0 +1,133 @@ +char rcsid_item[] = "$Id$"; + +#include "b.h" +#include +#include +#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 index 00000000000..3d6c5af5c48 --- /dev/null +++ b/utils/Burg/lex.c @@ -0,0 +1,260 @@ +char rcsid_lex[] = "$Id$"; + +#include +#include +#include +#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 index 00000000000..d3eefa27d09 --- /dev/null +++ b/utils/Burg/list.c @@ -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 index 00000000000..5c13698f1cb --- /dev/null +++ b/utils/Burg/main.c @@ -0,0 +1,182 @@ +char rcsid_main[] = "$Id$"; + +#include +#include +#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 index 00000000000..6c3c15454cd --- /dev/null +++ b/utils/Burg/map.c @@ -0,0 +1,135 @@ +char rcsid_map[] = "$Id$"; + +#include +#include +#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 index 00000000000..af88dd61ea9 --- /dev/null +++ b/utils/Burg/nonterminal.c @@ -0,0 +1,49 @@ +char rcsid_nonterminal[] = "$Id$"; + +#include "b.h" +#include + +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 index 00000000000..a6df9e304df --- /dev/null +++ b/utils/Burg/operator.c @@ -0,0 +1,48 @@ +char rcsid_operator[] = "$Id$"; + +#include "b.h" +#include + +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 index 00000000000..472aca579d0 --- /dev/null +++ b/utils/Burg/pattern.c @@ -0,0 +1,38 @@ +char rcsid_pattern[] = "$Id$"; + +#include +#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 index 00000000000..053304eafc3 --- /dev/null +++ b/utils/Burg/plank.c @@ -0,0 +1,920 @@ +char rcsid_plank[] = "$Id$"; + +#include +#include +#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 index 00000000000..76e5ea9b57b --- /dev/null +++ b/utils/Burg/queue.c @@ -0,0 +1,64 @@ +char rcsid_queue[] = "$Id$"; + +#include "b.h" +#include + +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 index 00000000000..ee5c89e8933 --- /dev/null +++ b/utils/Burg/rule.c @@ -0,0 +1,49 @@ +char rcsid_rule[] = "$Id$"; + +#include "b.h" +#include + +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 index 00000000000..e1f7283b6d6 --- /dev/null +++ b/utils/Burg/sample.gr @@ -0,0 +1,150 @@ +%{ +#include + +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 index 00000000000..9b69c3045ff --- /dev/null +++ b/utils/Burg/string.c @@ -0,0 +1,65 @@ +char rcsid_string[] = "$Id$"; + +#include +#include +#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 index 00000000000..3ecab2fc5ff --- /dev/null +++ b/utils/Burg/symtab.c @@ -0,0 +1,38 @@ +char rcsid_symtab[] = "$Id$"; + +#include +#include +#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 index 00000000000..1de74f9a107 --- /dev/null +++ b/utils/Burg/table.c @@ -0,0 +1,552 @@ +char rcsid_table[] = "$Id$"; + +#include "b.h" +#include +#include + +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 index 00000000000..05ee2d0f646 --- /dev/null +++ b/utils/Burg/trim.c @@ -0,0 +1,412 @@ +char rcsid_trim[] = "$Id$"; + +#include +#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 index 00000000000..bd50217308e --- /dev/null +++ b/utils/Burg/zalloc.c @@ -0,0 +1,35 @@ +char rcsid_zalloc[] = "$Id$"; + +#include +#include +#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); +}