diff options
Diffstat (limited to 'utils/Burg/plank.c')
-rw-r--r-- | utils/Burg/plank.c | 920 |
1 files changed, 920 insertions, 0 deletions
diff --git a/utils/Burg/plank.c b/utils/Burg/plank.c new file mode 100644 index 0000000..053304e --- /dev/null +++ b/utils/Burg/plank.c @@ -0,0 +1,920 @@ +char rcsid_plank[] = "$Id$"; + +#include <stdio.h> +#include <string.h> +#include "b.h" +#include "fe.h" + +#define ERROR_VAL 0 + +int speedflag = 0; + +Item_Set *sortedStates; +static struct stateMapTable smt; +int exceptionTolerance = 0; +static int plankSize = 32; + +static Plank newPlank ARGS((void)); +static PlankMap newPlankMap ARGS((int)); +static StateMap newStateMap ARGS((void)); +static Exception newException ARGS((int, int)); +static void enterStateMap ARGS((PlankMap, short *, int, int *)); +static List assemblePlanks ARGS((void)); +static void assignRules ARGS((RuleAST)); +static int stateCompare ARGS((Item_Set *, Item_Set *)); +static int ruleCompare ARGS((RuleAST *, RuleAST *)); +static void renumber ARGS((void)); +static short * newVector ARGS((void)); +static int width ARGS((int)); +static PlankMap mapToPmap ARGS((Dimension)); +static void doDimPmaps ARGS((Operator)); +static void doNonTermPmaps ARGS((NonTerminal)); +static void makePmaps ARGS((void)); +static void outPlank ARGS((Plank)); +static void purgePlanks ARGS((List)); +static void inToEx ARGS((void)); +static void makePlankRuleMacros ARGS((void)); +static void makePlankRule ARGS((void)); +static void exceptionSwitch ARGS((List, char *, char *, char *, int, char *)); +static void doPlankLabel ARGS((Operator)); +static void doPlankLabelSafely ARGS((Operator)); +static void doPlankLabelMacrosSafely ARGS((Operator)); +static void makePlankState ARGS((void)); + +static Plank +newPlank() +{ + Plank p; + char buf[50]; + static int num = 0; + + p = (Plank) zalloc(sizeof(struct plank)); + sprintf(buf, "%s_plank_%d", prefix, num++); + p->name = (char *) zalloc(strlen(buf)+1); + strcpy(p->name, buf); + return p; +} + +static PlankMap +newPlankMap(offset) int offset; +{ + PlankMap im; + + im = (PlankMap) zalloc(sizeof(struct plankMap)); + im->offset = offset; + return im; +} + +static StateMap +newStateMap() +{ + char buf[50]; + static int num = 0; + + StateMap sm; + + sm = (StateMap) zalloc(sizeof(struct stateMap)); + sprintf(buf, "f%d", num++); + sm->fieldname = (char *) zalloc(strlen(buf)+1); + strcpy(sm->fieldname, buf); + return sm; +} + +static Exception +newException(index, value) int index; int value; +{ + Exception e; + + e = (Exception) zalloc(sizeof(struct except)); + e->index = index; + e->value = value; + return e; +} + +static void +enterStateMap(im, v, width, new) PlankMap im; short * v; int width; int *new; +{ + int i; + StateMap sm; + List l; + int size; + + assert(im); + assert(v); + assert(width > 0); + size = globalMap->count; + + for (l = smt.maps; l; l = l->next) { + int ecount; + + sm = (StateMap) l->x; + ecount = 0; + for (i = 0; i < size; i++) { + if (v[i] != -1 && sm->value[i] != -1 && v[i] != sm->value[i]) { + if (++ecount > exceptionTolerance) { + goto again; + } + } + } + for (i = 0; i < size; i++) { + assert(v[i] >= 0); + assert(sm->value[i] >= 0); + if (v[i] == -1) { + continue; + } + if (sm->value[i] == -1) { + sm->value[i] = v[i]; + } else if (v[i] != sm->value[i]) { + im->exceptions = newList(newException(i,v[i]), im->exceptions); + } + } + im->values = sm; + if (width > sm->width) { + sm->width = width; + } + *new = 0; + return; + again: ; + } + sm = newStateMap(); + im->values = sm; + sm->value = v; + sm->width = width; + *new = 1; + smt.maps = newList(sm, smt.maps); +} + +static List +assemblePlanks() +{ + List planks = 0; + Plank pl; + List p; + List s; + + for (s = smt.maps; s; s = s->next) { + StateMap sm = (StateMap) s->x; + for (p = planks; p; p = p->next) { + pl = (Plank) p->x; + if (sm->width <= plankSize - pl->width) { + pl->width += sm->width; + pl->fields = newList(sm, pl->fields); + sm->plank = pl; + goto next; + } + } + pl = newPlank(); + pl->width = sm->width; + pl->fields = newList(sm, 0); + sm->plank = pl; + planks = appendList(pl, planks); + next: ; + } + return planks; +} + +RuleAST *sortedRules; + +static int count; + +static void +assignRules(ast) RuleAST ast; +{ + sortedRules[count++] = ast; +} + +static int +stateCompare(s, t) Item_Set *s; Item_Set *t; +{ + return strcmp((*s)->op->name, (*t)->op->name); +} + +static int +ruleCompare(s, t) RuleAST *s; RuleAST *t; +{ + return strcmp((*s)->lhs, (*t)->lhs); +} + +void +dumpSortedStates() +{ + int i; + + printf("dump Sorted States: "); + for (i = 0; i < globalMap->count; i++) { + printf("%d ", sortedStates[i]->num); + } + printf("\n"); +} + +void +dumpSortedRules() +{ + int i; + + printf("dump Sorted Rules: "); + for (i = 0; i < max_ruleAST; i++) { + printf("%d ", sortedRules[i]->rule->erulenum); + } + printf("\n"); +} + +static void +renumber() +{ + int i; + Operator previousOp; + NonTerminal previousLHS; + int base_counter; + + sortedStates = (Item_Set*) zalloc(globalMap->count * sizeof(Item_Set)); + for (i = 1; i < globalMap->count; i++) { + sortedStates[i-1] = globalMap->set[i]; + } + qsort(sortedStates, globalMap->count-1, sizeof(Item_Set), stateCompare); + previousOp = 0; + for (i = 0; i < globalMap->count-1; i++) { + sortedStates[i]->newNum = i; + sortedStates[i]->op->stateCount++; + if (previousOp != sortedStates[i]->op) { + sortedStates[i]->op->baseNum = i; + previousOp = sortedStates[i]->op; + } + } + + sortedRules = (RuleAST*) zalloc(max_ruleAST * sizeof(RuleAST)); + count = 0; + foreachList((ListFn) assignRules, ruleASTs); + qsort(sortedRules, max_ruleAST, sizeof(RuleAST), ruleCompare); + previousLHS = 0; + base_counter = 0; + for (i = 0; i < max_ruleAST; i++) { + if (previousLHS != sortedRules[i]->rule->lhs) { + sortedRules[i]->rule->lhs->baseNum = base_counter; + previousLHS = sortedRules[i]->rule->lhs; + base_counter++; /* make space for 0 */ + } + sortedRules[i]->rule->newNum = base_counter; + sortedRules[i]->rule->lhs->ruleCount++; + sortedRules[i]->rule->lhs->sampleRule = sortedRules[i]->rule; /* kludge for diagnostics */ + base_counter++; + } +} + +static short * +newVector() +{ + short *p; + p = (short *) zalloc(globalMap->count* sizeof(short)); + return p; +} + +static int +width(v) int v; +{ + int c; + + for (c = 0; v; v >>= 1) { + c++; + } + return c; + +} + +static PlankMap +mapToPmap(d) Dimension d; +{ + PlankMap im; + short *v; + int i; + int new; + + if (d->map->count == 1) { + return 0; + } + assert(d->map->count > 1); + im = newPlankMap(0); + v = newVector(); + for (i = 0; i < globalMap->count-1; i++) { + int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num; + assert(index >= 0); + v[i+1] = index; + } + v[0] = 0; + enterStateMap(im, v, width(d->map->count), &new); + if (!new) { + zfree(v); + } + return im; +} + +static void +doDimPmaps(op) Operator op; +{ + int i, j; + Dimension d; + short *v; + PlankMap im; + int new; + + if (!op->table->rules) { + return; + } + switch (op->arity) { + case 0: + break; + case 1: + d = op->table->dimen[0]; + if (d->map->count > 1) { + v = newVector(); + im = newPlankMap(op->baseNum); + for (i = 0; i < globalMap->count-1; i++) { + int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num; + if (index) { + Item_Set *ts = transLval(op->table, index, 0); + v[i+1] = (*ts)->newNum - op->baseNum+1; + assert(v[i+1] >= 0); + } + } + enterStateMap(im, v, width(d->map->count-1), &new); + if (!new) { + zfree(v); + } + d->pmap = im; + } + break; + case 2: + if (op->table->dimen[0]->map->count == 1 && op->table->dimen[1]->map->count == 1) { + op->table->dimen[0]->pmap = 0; + op->table->dimen[1]->pmap = 0; + } else if (op->table->dimen[0]->map->count == 1) { + v = newVector(); + im = newPlankMap(op->baseNum); + d = op->table->dimen[1]; + for (i = 0; i < globalMap->count-1; i++) { + int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num; + if (index) { + Item_Set *ts = transLval(op->table, 1, index); + v[i+1] = (*ts)->newNum - op->baseNum+1; + assert(v[i+1] >= 0); + } + } + enterStateMap(im, v, width(d->map->count-1), &new); + if (!new) { + zfree(v); + } + d->pmap = im; + } else if (op->table->dimen[1]->map->count == 1) { + v = newVector(); + im = newPlankMap(op->baseNum); + d = op->table->dimen[0]; + for (i = 0; i < globalMap->count-1; i++) { + int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num; + if (index) { + Item_Set *ts = transLval(op->table, index, 1); + v[i +1] = (*ts)->newNum - op->baseNum +1; + assert(v[i +1] >= 0); + } + } + enterStateMap(im, v, width(d->map->count-1), &new); + if (!new) { + zfree(v); + } + d->pmap = im; + } else { + op->table->dimen[0]->pmap = mapToPmap(op->table->dimen[0]); + op->table->dimen[1]->pmap = mapToPmap(op->table->dimen[1]); + /* output table */ + fprintf(outfile, "static unsigned %s %s_%s_transition[%d][%d] = {", + op->stateCount <= 255 ? "char" : "short", + prefix, + op->name, + op->table->dimen[0]->map->count, + op->table->dimen[1]->map->count); + for (i = 0; i < op->table->dimen[0]->map->count; i++) { + if (i > 0) { + fprintf(outfile, ","); + } + fprintf(outfile, "\n{"); + for (j = 0; j < op->table->dimen[1]->map->count; j++) { + Item_Set *ts = transLval(op->table, i, j); + short diff; + if (j > 0) { + fprintf(outfile, ","); + if (j % 10 == 0) { + fprintf(outfile, "\t/* row %d, cols %d-%d*/\n", + i, + j-10, + j-1); + } + } + if ((*ts)->num > 0) { + diff = (*ts)->newNum - op->baseNum +1; + } else { + diff = 0; + } + fprintf(outfile, "%5d", diff); + } + fprintf(outfile, "}\t/* row %d */", i); + } + fprintf(outfile, "\n};\n"); + } + break; + default: + assert(0); + } +} + +static NonTerminal *ntVector; + +static void +doNonTermPmaps(n) NonTerminal n; +{ + short *v; + PlankMap im; + int new; + int i; + + ntVector[n->num] = n; + if (n->num >= last_user_nonterminal) { + return; + } + if (n->ruleCount <= 0) { + return; + } + im = newPlankMap(n->baseNum); + v = newVector(); + for (i = 0; i < globalMap->count-1; i++) { + Rule r = globalMap->set[sortedStates[i]->num]->closed[n->num].rule; + if (r) { + r->used = 1; + v[i+1] = r->newNum - n->baseNum /*safely*/; + assert(v[i+1] >= 0); + } + } + enterStateMap(im, v, width(n->ruleCount+1), &new); + if (!new) { + zfree(v); + } + n->pmap = im; +} + +static void +makePmaps() +{ + foreachList((ListFn) doDimPmaps, operators); + ntVector = (NonTerminal*) zalloc((max_nonterminal) * sizeof(NonTerminal)); + foreachList((ListFn) doNonTermPmaps, nonterminals); +} + +static void +outPlank(p) Plank p; +{ + List f; + int i; + + fprintf(outfile, "static struct {\n"); + + for (f = p->fields; f; f = f->next) { + StateMap sm = (StateMap) f->x; + fprintf(outfile, "\tunsigned int %s:%d;\n", sm->fieldname, sm->width); + } + + fprintf(outfile, "} %s[] = {\n", p->name); + + for (i = 0; i < globalMap->count; i++) { + fprintf(outfile, "\t{"); + for (f = p->fields; f; f = f->next) { + StateMap sm = (StateMap) f->x; + fprintf(outfile, "%4d,", sm->value[i] == -1 ? ERROR_VAL : sm->value[i]); + } + fprintf(outfile, "},\t/* row %d */\n", i); + } + + fprintf(outfile, "};\n"); +} + +static void +purgePlanks(planks) List planks; +{ + List p; + + for (p = planks; p; p = p->next) { + Plank x = (Plank) p->x; + outPlank(x); + } +} + +static void +inToEx() +{ + int i; + int counter; + + fprintf(outfile, "static short %s_eruleMap[] = {\n", prefix); + counter = 0; + for (i = 0; i < max_ruleAST; i++) { + if (counter > 0) { + fprintf(outfile, ","); + if (counter % 10 == 0) { + fprintf(outfile, "\t/* %d-%d */\n", counter-10, counter-1); + } + } + if (counter < sortedRules[i]->rule->newNum) { + assert(counter == sortedRules[i]->rule->newNum-1); + fprintf(outfile, "%5d", 0); + counter++; + if (counter > 0) { + fprintf(outfile, ","); + if (counter % 10 == 0) { + fprintf(outfile, "\t/* %d-%d */\n", counter-10, counter-1); + } + } + } + fprintf(outfile, "%5d", sortedRules[i]->rule->erulenum); + counter++; + } + fprintf(outfile, "\n};\n"); +} + +static void +makePlankRuleMacros() +{ + int i; + + for (i = 1; i < last_user_nonterminal; i++) { + List es; + PlankMap im = ntVector[i]->pmap; + fprintf(outfile, "#define %s_%s_rule(state)\t", prefix, ntVector[i]->name); + if (im) { + fprintf(outfile, "%s_eruleMap[", prefix); + for (es = im->exceptions; es; es = es->next) { + Exception e = (Exception) es->x; + fprintf(outfile, "((state) == %d ? %d :", + e->index, e->value); + } + fprintf(outfile, "%s[state].%s", + im->values->plank->name, + im->values->fieldname); + for (es = im->exceptions; es; es = es->next) { + fprintf(outfile, ")"); + } + fprintf(outfile, " +%d]", im->offset); + + } else { + /* nonterminal never appears on LHS. */ + assert(ntVector[i] == start); + fprintf(outfile, "0"); + } + fprintf(outfile, "\n"); + } + fprintf(outfile, "\n"); +} + +static void +makePlankRule() +{ + int i; + + makePlankRuleMacros(); + + fprintf(outfile, "#ifdef __STDC__\n"); + fprintf(outfile, "int %s_rule(int state, int goalnt) {\n", prefix); + fprintf(outfile, "#else\n"); + fprintf(outfile, "int %s_rule(state, goalnt) int state; int goalnt; {\n", prefix); + fprintf(outfile, "#endif\n"); + + fprintf(outfile, + "\t%s_assert(state >= 0 && state < %d, %s_PANIC(\"Bad state %%d passed to %s_rule\\n\", state));\n", + prefix, globalMap->count, prefix, prefix); + fprintf(outfile, "\tswitch(goalnt) {\n"); + + for (i = 1; i < last_user_nonterminal; i++) { + fprintf(outfile, "\tcase %d:\n", i); + fprintf(outfile, "\t\treturn %s_%s_rule(state);\n", prefix, ntVector[i]->name); + } + fprintf(outfile, "\tdefault:\n"); + fprintf(outfile, "\t\t%s_PANIC(\"Unknown nonterminal %%d in %s_rule;\\n\", goalnt);\n", prefix, prefix); + fprintf(outfile, "\t\tabort();\n"); + fprintf(outfile, "\t\treturn 0;\n"); + fprintf(outfile, "\t}\n"); + fprintf(outfile, "}\n"); +} + +static void +exceptionSwitch(es, sw, pre, post, offset, def) List es; char *sw; char *pre; char *post; int offset; char *def; +{ + if (es) { + fprintf(outfile, "\t\tswitch (%s) {\n", sw); + for (; es; es = es->next) { + Exception e = (Exception) es->x; + fprintf(outfile, "\t\tcase %d: %s %d; %s\n", e->index, pre, e->value+offset, post); + } + if (def) { + fprintf(outfile, "\t\tdefault: %s;\n", def); + } + fprintf(outfile, "\t\t}\n"); + } else { + if (def) { + fprintf(outfile, "\t\t%s;\n", def); + } + } +} + +static void +doPlankLabel(op) Operator op; +{ + PlankMap im0; + PlankMap im1; + char buf[100]; + + fprintf(outfile, "\tcase %d:\n", op->num); + switch (op->arity) { + case 0: + fprintf(outfile, "\t\treturn %d;\n", op->table->transition[0]->newNum); + break; + case 1: + im0 = op->table->dimen[0]->pmap; + if (im0) { + exceptionSwitch(im0->exceptions, "l", "return ", "", im0->offset, 0); + fprintf(outfile, "\t\treturn %s[l].%s + %d;\n", + im0->values->plank->name, im0->values->fieldname, im0->offset); + } else { + Item_Set *ts = transLval(op->table, 1, 0); + if (*ts) { + fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum); + } else { + fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL); + } + } + break; + case 2: + im0 = op->table->dimen[0]->pmap; + im1 = op->table->dimen[1]->pmap; + if (!im0 && !im1) { + Item_Set *ts = transLval(op->table, 1, 1); + if (*ts) { + fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum); + } else { + fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL); + } + } else if (!im0) { + exceptionSwitch(im1->exceptions, "r", "return ", "", im1->offset, 0); + fprintf(outfile, "\t\treturn %s[r].%s + %d;\n", + im1->values->plank->name, im1->values->fieldname, im1->offset); + } else if (!im1) { + exceptionSwitch(im0->exceptions, "l", "return ", "", im0->offset, 0); + fprintf(outfile, "\t\treturn %s[l].%s + %d;\n", + im0->values->plank->name, im0->values->fieldname, im0->offset); + } else { + assert(im0->offset == 0); + assert(im1->offset == 0); + sprintf(buf, "l = %s[l].%s", + im0->values->plank->name, im0->values->fieldname); + exceptionSwitch(im0->exceptions, "l", "l =", "break;", 0, buf); + sprintf(buf, "r = %s[r].%s", + im1->values->plank->name, im1->values->fieldname); + exceptionSwitch(im1->exceptions, "r", "r =", "break;", 0, buf); + + fprintf(outfile, "\t\treturn %s_%s_transition[l][r] + %d;\n", + prefix, + op->name, + op->baseNum); + } + break; + default: + assert(0); + } +} + +static void +doPlankLabelMacrosSafely(op) Operator op; +{ + PlankMap im0; + PlankMap im1; + + switch (op->arity) { + case -1: + fprintf(outfile, "#define %s_%s_state\t0\n", prefix, op->name); + break; + case 0: + fprintf(outfile, "#define %s_%s_state", prefix, op->name); + fprintf(outfile, "\t%d\n", op->table->transition[0]->newNum+1); + break; + case 1: + fprintf(outfile, "#define %s_%s_state(l)", prefix, op->name); + im0 = op->table->dimen[0]->pmap; + if (im0) { + if (im0->exceptions) { + List es = im0->exceptions; + assert(0); + fprintf(outfile, "\t\tswitch (l) {\n"); + for (; es; es = es->next) { + Exception e = (Exception) es->x; + fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im0->offset : 0); + } + fprintf(outfile, "\t\t}\n"); + } + if (speedflag) { + fprintf(outfile, "\t( %s[l].%s + %d )\n", + im0->values->plank->name, im0->values->fieldname, + im0->offset); + } else { + fprintf(outfile, "\t( (%s_TEMP = %s[l].%s) ? %s_TEMP + %d : 0 )\n", + prefix, + im0->values->plank->name, im0->values->fieldname, + prefix, + im0->offset); + } + } else { + Item_Set *ts = transLval(op->table, 1, 0); + if (*ts) { + fprintf(outfile, "\t%d\n", (*ts)->newNum+1); + } else { + fprintf(outfile, "\t%d\n", 0); + } + } + break; + case 2: + fprintf(outfile, "#define %s_%s_state(l,r)", prefix, op->name); + + im0 = op->table->dimen[0]->pmap; + im1 = op->table->dimen[1]->pmap; + if (!im0 && !im1) { + Item_Set *ts = transLval(op->table, 1, 1); + assert(0); + if (*ts) { + fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum+1); + } else { + fprintf(outfile, "\t\treturn %d;\n", 0); + } + } else if (!im0) { + assert(0); + if (im1->exceptions) { + List es = im1->exceptions; + fprintf(outfile, "\t\tswitch (r) {\n"); + for (; es; es = es->next) { + Exception e = (Exception) es->x; + fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im1->offset : 0); + } + fprintf(outfile, "\t\t}\n"); + } + fprintf(outfile, "\t\tstate = %s[r].%s; offset = %d;\n", + im1->values->plank->name, im1->values->fieldname, im1->offset); + fprintf(outfile, "\t\tbreak;\n"); + } else if (!im1) { + assert(0); + if (im0->exceptions) { + List es = im0->exceptions; + fprintf(outfile, "\t\tswitch (l) {\n"); + for (; es; es = es->next) { + Exception e = (Exception) es->x; + fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im0->offset : 0); + } + fprintf(outfile, "\t\t}\n"); + } + fprintf(outfile, "\t\tstate = %s[l].%s; offset = %d;\n", + im0->values->plank->name, im0->values->fieldname, im0->offset); + fprintf(outfile, "\t\tbreak;\n"); + } else { + assert(im0->offset == 0); + assert(im1->offset == 0); + /* + sprintf(buf, "l = %s[l].%s", + im0->values->plank->name, im0->values->fieldname); + exceptionSwitch(im0->exceptions, "l", "l =", "break;", 0, buf); + sprintf(buf, "r = %s[r].%s", + im1->values->plank->name, im1->values->fieldname); + exceptionSwitch(im1->exceptions, "r", "r =", "break;", 0, buf); + + fprintf(outfile, "\t\tstate = %s_%s_transition[l][r]; offset = %d;\n", + prefix, + op->name, + op->baseNum); + fprintf(outfile, "\t\tbreak;\n"); + */ + + if (speedflag) { + fprintf(outfile, "\t( %s_%s_transition[%s[l].%s][%s[r].%s] + %d)\n", + prefix, + op->name, + im0->values->plank->name, im0->values->fieldname, + im1->values->plank->name, im1->values->fieldname, + op->baseNum); + } else { + fprintf(outfile, "\t( (%s_TEMP = %s_%s_transition[%s[l].%s][%s[r].%s]) ? ", + prefix, + prefix, + op->name, + im0->values->plank->name, im0->values->fieldname, + im1->values->plank->name, im1->values->fieldname); + fprintf(outfile, "%s_TEMP + %d : 0 )\n", + prefix, + op->baseNum); + } + } + break; + default: + assert(0); + } +} +static void +doPlankLabelSafely(op) Operator op; +{ + fprintf(outfile, "\tcase %d:\n", op->num); + switch (op->arity) { + case -1: + fprintf(outfile, "\t\treturn 0;\n"); + break; + case 0: + fprintf(outfile, "\t\treturn %s_%s_state;\n", prefix, op->name); + break; + case 1: + fprintf(outfile, "\t\treturn %s_%s_state(l);\n", prefix, op->name); + break; + case 2: + fprintf(outfile, "\t\treturn %s_%s_state(l,r);\n", prefix, op->name); + break; + default: + assert(0); + } +} + +static void +makePlankState() +{ + fprintf(outfile, "\n"); + fprintf(outfile, "int %s_TEMP;\n", prefix); + foreachList((ListFn) doPlankLabelMacrosSafely, operators); + fprintf(outfile, "\n"); + + fprintf(outfile, "#ifdef __STDC__\n"); + switch (max_arity) { + case -1: + fprintf(stderr, "ERROR: no terminals in grammar.\n"); + exit(1); + case 0: + fprintf(outfile, "int %s_state(int op) {\n", prefix); + fprintf(outfile, "#else\n"); + fprintf(outfile, "int %s_state(op) int op; {\n", prefix); + break; + case 1: + fprintf(outfile, "int %s_state(int op, int l) {\n", prefix); + fprintf(outfile, "#else\n"); + fprintf(outfile, "int %s_state(op, l) int op; int l; {\n", prefix); + break; + case 2: + fprintf(outfile, "int %s_state(int op, int l, int r) {\n", prefix); + fprintf(outfile, "#else\n"); + fprintf(outfile, "int %s_state(op, l, r) int op; int l; int r; {\n", prefix); + break; + default: + assert(0); + } + fprintf(outfile, "#endif\n"); + + fprintf(outfile, "\tregister int %s_TEMP;\n", prefix); + + fprintf(outfile, "#ifndef NDEBUG\n"); + + fprintf(outfile, "\tswitch (op) {\n"); + opsOfArity(2); + if (max_arity >= 2) { + fprintf(outfile, + "\t\t%s_assert(r >= 0 && r < %d, %s_PANIC(\"Bad state %%d passed to %s_state\\n\", r));\n", + prefix, globalMap->count, prefix, prefix); + fprintf(outfile, "\t\t/*FALLTHROUGH*/\n"); + } + opsOfArity(1); + if (max_arity > 1) { + fprintf(outfile, + "\t\t%s_assert(l >= 0 && l < %d, %s_PANIC(\"Bad state %%d passed to %s_state\\n\", l));\n", + prefix, globalMap->count, prefix, prefix); + fprintf(outfile, "\t\t/*FALLTHROUGH*/\n"); + } + opsOfArity(0); + fprintf(outfile, "\t\tbreak;\n"); + fprintf(outfile, "\t}\n"); + fprintf(outfile, "#endif\n"); + + fprintf(outfile, "\tswitch (op) {\n"); + fprintf(outfile,"\tdefault: %s_PANIC(\"Unknown op %%d in %s_state\\n\", op); abort(); return 0;\n", + prefix, prefix); + foreachList((ListFn) doPlankLabelSafely, operators); + fprintf(outfile, "\t}\n"); + + fprintf(outfile, "}\n"); +} + +void +makePlanks() +{ + List planks; + renumber(); + makePmaps(); + planks = assemblePlanks(); + purgePlanks(planks); + inToEx(); + makePlankRule(); + makePlankState(); +} |