| char rcsid_be[] = "$Id$"; |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include "b.h" |
| #include "fe.h" |
| |
| #define ERROR_VAL 0 |
| |
| FILE *outfile; |
| const 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, const 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"); |
| } |
| |
| static int seminal(int from, int 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] != 0, 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"); |
| 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(RuleAST r, const 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 t1, t2; |
| |
| fprintf(outfile, "{"); |
| fprintf(outfile, "%5d, %5d, %5d, %5d", |
| pVector[i]->rule->lhs->num, |
| (o = pVector[i]->rule->pat->op) ? o->num : 0, |
| (t1 = pVector[i]->rule->pat->children[0]) ? t1->num : 0, |
| (t2 = pVector[i]->rule->pat->children[1]) ? t2->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); |
| } |