X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/1a2b5d37e1d44b47cd51220945f4ba29c228a419..11652ab3dc44bf12d5fa9095d1495b5cd3102ff7:/src/reduce.c diff --git a/src/reduce.c b/src/reduce.c index c4a2bd1c..58bf43ea 100644 --- a/src/reduce.c +++ b/src/reduce.c @@ -34,65 +34,29 @@ #include "reduce.h" #include "reader.h" #include "getargs.h" +#include "bitset.h" -typedef unsigned *BSet; typedef short *rule; /* Set of all nonterminals which are not useless. */ -static BSet N; +static bitset N; /* Set of all rules which have no useless nonterminals in their RHS. */ -static BSet P; +static bitset P; /* Set of all accessible symbols. */ -static BSet V; +static bitset V; /* Set of symbols used to define rule precedence (so they are `useless', but no warning should be issued). */ -static BSet V1; +static bitset V1; static int nuseful_productions; static int nuseless_productions; static int nuseful_nonterminals; int nuseless_nonterminals; -static bool -bits_equal (BSet L, BSet R, int n) -{ - int i; - - for (i = n - 1; i >= 0; i--) - if (L[i] != R[i]) - return FALSE; - return TRUE; -} - - -static int -nbits (unsigned i) -{ - int count = 0; - - while (i != 0) - { - i ^= (i & ((unsigned) (-(int) i))); - ++count; - } - return count; -} - - -static int -bits_size (BSet S, int n) -{ - int i, count = 0; - - for (i = n - 1; i >= 0; i--) - count += nbits (S[i]); - return count; -} - /*-------------------------------------------------------------------. | Another way to do this would be with a set for each production and | | then do subset tests against N0, but even for the C grammar the | @@ -100,7 +64,7 @@ bits_size (BSet S, int n) `-------------------------------------------------------------------*/ static bool -useful_production (int i, BSet N0) +useful_production (int i, bitset N0) { rule r; short n; @@ -108,10 +72,9 @@ useful_production (int i, BSet N0) /* A production is useful if all of the nonterminals in its appear in the set of useful nonterminals. */ - for (r = &ritem[rules[i].rhs]; *r >= 0; r++) - if (ISVAR (n = *r)) - if (!BITISSET (N0, n - ntokens)) - return FALSE; + for (r = rules[i].rhs; *r >= 0; r++) + if (ISVAR (n = *r) && !bitset_test (N0, n - ntokens)) + return FALSE; return TRUE; } @@ -123,13 +86,14 @@ useful_production (int i, BSet N0) static void useless_nonterminals (void) { - BSet Np, Ns; + bitset Np, Ns; int i; /* N is set as built. Np is set being built this iteration. P is set of all productions which have a RHS all in N. */ - Np = XCALLOC (unsigned, WORDSIZE (nvars)); + Np = bitset_create (nvars, BITSET_FIXED); + /* The set being computed is a set of nonterminals which can derive the empty string or strings consisting of all terminals. At each @@ -149,26 +113,21 @@ useless_nonterminals (void) while (1) { - for (i = WORDSIZE (nvars) - 1; i >= 0; i--) - Np[i] = N[i]; - for (i = 1; i <= nrules; i++) - { - if (!BITISSET (P, i)) - { - if (useful_production (i, N)) - { - SETBIT (Np, rules[i].lhs - ntokens); - SETBIT (P, i); - } - } - } - if (bits_equal (N, Np, WORDSIZE (nvars))) + bitset_copy (Np, N); + for (i = 1; i < nrules + 1; i++) + if (!bitset_test (P, i) + && useful_production (i, N)) + { + bitset_set (Np, rules[i].lhs - ntokens); + bitset_set (P, i); + } + if (bitset_equal_p (N, Np)) break; Ns = Np; Np = N; N = Ns; } - XFREE (N); + bitset_free (N); N = Np; } @@ -176,7 +135,7 @@ useless_nonterminals (void) static void inaccessable_symbols (void) { - BSet Vp, Vs, Pp; + bitset Vp, Vs, Pp; int i; short t; rule r; @@ -204,31 +163,30 @@ inaccessable_symbols (void) terminals are printed (if running in verbose mode) so that the user can know. */ - Vp = XCALLOC (unsigned, WORDSIZE (nsyms)); - Pp = XCALLOC (unsigned, WORDSIZE (nrules + 1)); + Vp = bitset_create (nsyms, BITSET_FIXED); + Pp = bitset_create (nrules + 1, BITSET_FIXED); /* If the start symbol isn't useful, then nothing will be useful. */ - if (BITISSET (N, start_symbol - ntokens)) + if (bitset_test (N, start_symbol - ntokens)) { - SETBIT (V, start_symbol); + bitset_set (V, start_symbol); while (1) { - for (i = WORDSIZE (nsyms) - 1; i >= 0; i--) - Vp[i] = V[i]; - for (i = 1; i <= nrules; i++) + bitset_copy (Vp, V); + for (i = 1; i < nrules + 1; i++) { - if (!BITISSET (Pp, i) - && BITISSET (P, i) - && BITISSET (V, rules[i].lhs)) + if (!bitset_test (Pp, i) + && bitset_test (P, i) + && bitset_test (V, rules[i].lhs)) { - for (r = &ritem[rules[i].rhs]; *r >= 0; r++) - if (ISTOKEN (t = *r) || BITISSET (N, t - ntokens)) - SETBIT (Vp, t); - SETBIT (Pp, i); + for (r = rules[i].rhs; *r >= 0; r++) + if (ISTOKEN (t = *r) || bitset_test (N, t - ntokens)) + bitset_set (Vp, t); + bitset_set (Pp, i); } } - if (bits_equal (V, Vp, WORDSIZE (nsyms))) + if (bitset_equal_p (V, Vp)) break; Vs = Vp; Vp = V; @@ -236,30 +194,30 @@ inaccessable_symbols (void) } } - XFREE (V); + bitset_free (V); V = Vp; /* Tokens 0, 1, and 2 are internal to Bison. Consider them useful. */ - SETBIT (V, 0); /* end-of-input token */ - SETBIT (V, 1); /* error token */ - SETBIT (V, 2); /* some undefined token */ + bitset_set (V, 0); /* end-of-input token */ + bitset_set (V, 1); /* error token */ + bitset_set (V, 2); /* some undefined token */ - XFREE (P); + bitset_free (P); P = Pp; - nuseful_productions = bits_size (P, WORDSIZE (nrules + 1)); + nuseful_productions = bitset_count (P); nuseless_productions = nrules - nuseful_productions; nuseful_nonterminals = 0; for (i = ntokens; i < nsyms; i++) - if (BITISSET (V, i)) + if (bitset_test (V, i)) nuseful_nonterminals++; nuseless_nonterminals = nvars - nuseful_nonterminals; /* A token that was used in %prec should not be warned about. */ - for (i = 1; i < nrules; i++) + for (i = 1; i < nrules + 1; i++) if (rules[i].precsym != 0) - SETBIT (V1, rules[i].precsym); + bitset_set (V1, rules[i].precsym); } static void @@ -283,8 +241,8 @@ reduce_grammar_tables (void) np = 0; ni = 0; - for (pn = 1; pn <= nrules; pn++) - if (BITISSET (P, pn)) + for (pn = 1; pn < nrules + 1; pn++) + if (bitset_test (P, pn)) { np++; if (pn != np) @@ -294,10 +252,10 @@ reduce_grammar_tables (void) rules[np].prec = rules[pn].prec; rules[np].assoc = rules[pn].assoc; rules[np].rhs = rules[pn].rhs; - if (rules[np].rhs != ni) + if (rules[np].rhs - ritem != ni) { - pi = rules[np].rhs; - rules[np].rhs = ni; + pi = rules[np].rhs - ritem; + rules[np].rhs = ritem + ni; while (ritem[pi] >= 0) ritem[ni++] = ritem[pi++]; ritem[ni++] = -np; @@ -323,8 +281,8 @@ reduce_grammar_tables (void) if (nuseless_productions > 0) { int pn; - for (pn = 1; pn <= nrules; pn++) - rules[pn].useful = BITISSET (P, pn); + for (pn = 1; pn < nrules + 1; pn++) + rules[pn].useful = bitset_test (P, pn); } } @@ -337,7 +295,6 @@ static void nonterminals_reduce (void) { int i, n; - rule r; /* Map the nonterminals to their new index: useful first, useless afterwards. Kept for later report. */ @@ -345,10 +302,10 @@ nonterminals_reduce (void) short *nontermmap = XCALLOC (short, nvars) - ntokens; n = ntokens; for (i = ntokens; i < nsyms; i++) - if (BITISSET (V, i)) + if (bitset_test (V, i)) nontermmap[i] = n++; for (i = ntokens; i < nsyms; i++) - if (!BITISSET (V, i)) + if (!bitset_test (V, i)) nontermmap[i] = n++; @@ -365,7 +322,7 @@ nonterminals_reduce (void) /* Replace all symbol numbers in valid data structures. */ - for (i = 1; i <= nrules; i++) + for (i = 1; i < nrules + 1; i++) { rules[i].lhs = nontermmap[rules[i].lhs]; if (ISVAR (rules[i].precsym)) @@ -406,7 +363,7 @@ reduce_output (FILE *out) bool b = FALSE; int i; for (i = 0; i < ntokens; i++) - if (!BITISSET (V, i) && !BITISSET (V1, i)) + if (!bitset_test (V, i) && !bitset_test (V1, i)) { if (!b) fprintf (out, "%s\n\n", _("Terminals which are not used:")); @@ -421,13 +378,13 @@ reduce_output (FILE *out) { int i; fprintf (out, "%s\n\n", _("Useless rules:")); - for (i = 1; i <= nrules; i++) + for (i = 1; i < nrules + 1; i++) if (!rules[i].useful) { rule r; fprintf (out, "#%-4d ", i - 1); fprintf (out, "%s:", symbols[rules[i].lhs]->tag); - for (r = &ritem[rules[i].rhs]; *r >= 0; r++) + for (r = rules[i].rhs; *r >= 0; r++) fprintf (out, " %s", symbols[*r]->tag); fputs (";\n", out); } @@ -454,28 +411,28 @@ dump_grammar (FILE *out) fprintf (out, "\n\n"); fprintf (out, "Rules\n-----\n\n"); fprintf (out, "Num (Prec, Assoc, Useful, Ritem Range) Lhs -> Rhs (Ritem range) [Num]\n"); - for (i = 1; i <= nrules; i++) + for (i = 1; i < nrules + 1; i++) { int rhs_count = 0; /* Find the last RHS index in ritems. */ - for (r = &ritem[rules[i].rhs]; *r >= 0; ++r) + for (r = rules[i].rhs; *r >= 0; ++r) ++rhs_count; fprintf (out, "%3d (%2d, %2d, %2d, %2d-%2d) %2d ->", i - 1, rules[i].prec, rules[i].assoc, rules[i].useful, - rules[i].rhs, rules[i].rhs + rhs_count - 1, + rules[i].rhs - ritem, rules[i].rhs - ritem + rhs_count - 1, rules[i].lhs); /* Dumped the RHS. */ - for (r = &ritem[rules[i].rhs]; *r >= 0; r++) + for (r = rules[i].rhs; *r >= 0; r++) fprintf (out, "%3d", *r); fprintf (out, " [%d]\n", -(*r) - 1); } fprintf (out, "\n\n"); fprintf (out, "Rules interpreted\n-----------------\n\n"); - for (i = 1; i <= nrules; i++) + for (i = 1; i < nrules + 1; i++) { fprintf (out, "%-5d %s :", i, symbols[rules[i].lhs]->tag); - for (r = &ritem[rules[i].rhs]; *r >= 0; r++) + for (r = rules[i].rhs; *r >= 0; r++) fprintf (out, " %s", symbols[*r]->tag); fputc ('\n', out); } @@ -524,22 +481,21 @@ reduce_grammar (void) /* Allocate the global sets used to compute the reduced grammar */ - N = XCALLOC (unsigned, WORDSIZE (nvars)); - P = XCALLOC (unsigned, WORDSIZE (nrules + 1)); - V = XCALLOC (unsigned, WORDSIZE (nsyms)); - V1 = XCALLOC (unsigned, WORDSIZE (nsyms)); + N = bitset_create (nvars, BITSET_FIXED); + P = bitset_create (nrules + 1, BITSET_FIXED); + V = bitset_create (nsyms, BITSET_FIXED); + V1 = bitset_create (nsyms, BITSET_FIXED); useless_nonterminals (); inaccessable_symbols (); reduced = (bool) (nuseless_nonterminals + nuseless_productions > 0); - if (!reduced) return; reduce_print (); - if (!BITISSET (N, start_symbol - ntokens)) + if (!bitset_test (N, start_symbol - ntokens)) fatal (_("Start symbol %s does not derive any sentence"), symbols[start_symbol]->tag); @@ -565,8 +521,8 @@ reduce_grammar (void) void reduce_free (void) { - XFREE (N); - XFREE (V); - XFREE (V1); - XFREE (P); + bitset_free (N); + bitset_free (V); + bitset_free (V1); + bitset_free (P); }