| char rcsid_plank[] = "$Id$"; |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include <stdlib.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, const char *, const char *, const char *, int, const 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), (int(*)(const void *, const void *))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), (int(*)(const void *, const void *))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; const char *sw; const char *pre; const char *post; int offset; const 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(); |
| } |