#include "defs.h" #if defined(KYLEP_CHANGE) /* BYACC prototypes, with type safety */ void find_final_state(); void remove_conflicts(); void unused_rules(); void total_conflicts(); void defreds(); #endif // KYLEP_CHANGE action **parser; int SRtotal; int RRtotal; short *SRconflicts; short *RRconflicts; short *defred; short *rules_used; short nunused; short final_state; static int SRcount; static int RRcount; extern action *parse_actions(); extern action *get_shifts(); extern action *add_reductions(); extern action *add_reduce(); #if defined(KYLEP_CHANGE) void #endif make_parser() { register int i; parser = NEW2(nstates, action *); for (i = 0; i < nstates; i++) parser[i] = parse_actions(i); find_final_state(); remove_conflicts(); unused_rules(); if (SRtotal + RRtotal > 0) total_conflicts(); defreds(); } action * parse_actions(stateno) register int stateno; { register action *actions; actions = get_shifts(stateno); actions = add_reductions(stateno, actions); return (actions); } action * get_shifts(stateno) int stateno; { register action *actions, *temp; register shifts *sp; register short *to_state; register int i, k; register int symbol; actions = 0; sp = shift_table[stateno]; if (sp) { to_state = sp->shift; for (i = sp->nshifts - 1; i >= 0; i--) { k = to_state[i]; symbol = accessing_symbol[k]; if (ISTOKEN(symbol)) { temp = NEW(action); temp->next = actions; #if defined(KYLEP_CHANGE) temp->symbol = (short) symbol; temp->number = (short) k; #else temp->symbol = symbol; temp->number = k; #endif // KYLEP_CHANGE temp->prec = symbol_prec[symbol]; temp->action_code = SHIFT; temp->assoc = symbol_assoc[symbol]; actions = temp; } } } return (actions); } action * add_reductions(stateno, actions) int stateno; register action *actions; { register int i, j, m, n; register int ruleno, tokensetsize; register unsigned *rowp; tokensetsize = WORDSIZE(ntokens); m = lookaheads[stateno]; n = lookaheads[stateno + 1]; for (i = m; i < n; i++) { ruleno = LAruleno[i]; rowp = LA + i * tokensetsize; for (j = ntokens - 1; j >= 0; j--) { if (BIT(rowp, j)) actions = add_reduce(actions, ruleno, j); } } return (actions); } action * add_reduce(actions, ruleno, symbol) register action *actions; register int ruleno, symbol; { register action *temp, *prev, *next; prev = 0; for (next = actions; next && next->symbol < symbol; next = next->next) prev = next; while (next && next->symbol == symbol && next->action_code == SHIFT) { prev = next; next = next->next; } while (next && next->symbol == symbol && next->action_code == REDUCE && next->number < ruleno) { prev = next; next = next->next; } temp = NEW(action); temp->next = next; #if defined(KYLEP_CHANGE) temp->symbol = (short) symbol; temp->number = (short) ruleno; #else temp->symbol = symbol; temp->number = ruleno; #endif // KYLEP_CHANGE temp->prec = rprec[ruleno]; temp->action_code = REDUCE; temp->assoc = rassoc[ruleno]; if (prev) prev->next = temp; else actions = temp; return (actions); } #if defined(KYLEP_CHANGE) void #endif find_final_state() { register int goal, i; register short *to_state; register shifts *p; p = shift_table[0]; to_state = p->shift; goal = ritem[1]; for (i = p->nshifts - 1; i >= 0; --i) { final_state = to_state[i]; if (accessing_symbol[final_state] == goal) break; } } #if defined(KYLEP_CHANGE) void #endif unused_rules() { register int i; register action *p; rules_used = (short *) MALLOC(nrules*sizeof(short)); if (rules_used == 0) no_space(); for (i = 0; i < nrules; ++i) rules_used[i] = 0; for (i = 0; i < nstates; ++i) { for (p = parser[i]; p; p = p->next) { if (p->action_code == REDUCE && p->suppressed == 0) rules_used[p->number] = 1; } } nunused = 0; for (i = 3; i < nrules; ++i) if (!rules_used[i]) ++nunused; if (nunused) if (nunused == 1) fprintf(stderr, "%s: 1 rule never reduced\n", myname); else fprintf(stderr, "%s: %d rules never reduced\n", myname, nunused); } #if defined(KYLEP_CHANGE) void #endif remove_conflicts() { register int i; register int symbol; register action *p, *pref; SRtotal = 0; RRtotal = 0; SRconflicts = NEW2(nstates, short); RRconflicts = NEW2(nstates, short); for (i = 0; i < nstates; i++) { SRcount = 0; RRcount = 0; symbol = -1; for (p = parser[i]; p; p = p->next) { if (p->symbol != symbol) { pref = p; symbol = p->symbol; } else if (i == final_state && symbol == 0) { SRcount++; p->suppressed = 1; } else if (pref->action_code == SHIFT) { if (pref->prec > 0 && p->prec > 0) { if (pref->prec < p->prec) { pref->suppressed = 2; pref = p; } else if (pref->prec > p->prec) { p->suppressed = 2; } else if (pref->assoc == LEFT) { pref->suppressed = 2; pref = p; } else if (pref->assoc == RIGHT) { p->suppressed = 2; } else { pref->suppressed = 2; p->suppressed = 2; } } else { SRcount++; p->suppressed = 1; } } else { RRcount++; p->suppressed = 1; } } SRtotal += SRcount; RRtotal += RRcount; #if defined(KYLEP_CHANGE) SRconflicts[i] = (short) SRcount; RRconflicts[i] = (short) RRcount; #else SRconflicts[i] = SRcount; RRconflicts[i] = RRcount; #endif // KYLEP_CHANGE } } #if defined(KYLEP_CHANGE) void #endif total_conflicts() { fprintf(stderr, "%s: ", myname); if (SRtotal == 1) fprintf(stderr, "1 shift/reduce conflict"); else if (SRtotal > 1) fprintf(stderr, "%d shift/reduce conflicts", SRtotal); if (SRtotal && RRtotal) fprintf(stderr, ", "); if (RRtotal == 1) fprintf(stderr, "1 reduce/reduce conflict"); else if (RRtotal > 1) fprintf(stderr, "%d reduce/reduce conflicts", RRtotal); fprintf(stderr, ".\n"); } int sole_reduction(stateno) int stateno; { register int count, ruleno; register action *p; count = 0; ruleno = 0; for (p = parser[stateno]; p; p = p->next) { if (p->action_code == SHIFT && p->suppressed == 0) return (0); else if (p->action_code == REDUCE && p->suppressed == 0) { if (ruleno > 0 && p->number != ruleno) return (0); if (p->symbol != 1) ++count; ruleno = p->number; } } if (count == 0) return (0); return (ruleno); } #if defined(KYLEP_CHANGE) void #endif defreds() { register int i; defred = NEW2(nstates, short); for (i = 0; i < nstates; i++) #if defined(KYLEP_CHANGE) defred[i] = (short) sole_reduction(i); #else defred[i] = sole_reduction(i); #endif // KYLEP_CHANGE } free_action_row(p) register action *p; { register action *q; while (p) { q = p->next; FREE(p); p = q; } } #if defined(KYLEP_CHANGE) void #endif free_parser() { register int i; for (i = 0; i < nstates; i++) free_action_row(parser[i]); FREE(parser); }