34 |
#include "reduce.h" |
#include "reduce.h" |
35 |
#include "reader.h" |
#include "reader.h" |
36 |
#include "getargs.h" |
#include "getargs.h" |
37 |
|
#include "bitset.h" |
38 |
|
|
|
typedef unsigned *BSet; |
|
39 |
typedef short *rule; |
typedef short *rule; |
40 |
|
|
41 |
|
|
42 |
/* Set of all nonterminals which are not useless. */ |
/* Set of all nonterminals which are not useless. */ |
43 |
static BSet N; |
static bitset N; |
44 |
|
|
45 |
/* Set of all rules which have no useless nonterminals in their RHS. */ |
/* Set of all rules which have no useless nonterminals in their RHS. */ |
46 |
static BSet P; |
static bitset P; |
47 |
|
|
48 |
/* Set of all accessible symbols. */ |
/* Set of all accessible symbols. */ |
49 |
static BSet V; |
static bitset V; |
50 |
|
|
51 |
/* Set of symbols used to define rule precedence (so they are |
/* Set of symbols used to define rule precedence (so they are |
52 |
`useless', but no warning should be issued). */ |
`useless', but no warning should be issued). */ |
53 |
static BSet V1; |
static bitset V1; |
54 |
|
|
55 |
static int nuseful_productions; |
static int nuseful_productions; |
56 |
static int nuseless_productions; |
static int nuseless_productions; |
57 |
static int nuseful_nonterminals; |
static int nuseful_nonterminals; |
58 |
int nuseless_nonterminals; |
int nuseless_nonterminals; |
59 |
|
|
|
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; |
|
|
} |
|
|
|
|
|
|
|
60 |
static int |
static int |
61 |
bits_size (BSet S, int n) |
bits_size (bitset S) |
62 |
{ |
{ |
63 |
int i, count = 0; |
int i, count = 0; |
64 |
|
|
65 |
for (i = n - 1; i >= 0; i--) |
BITSET_EXECUTE (S, 0, i, { ++count; }); |
|
count += nbits (S[i]); |
|
66 |
return count; |
return count; |
67 |
} |
} |
68 |
|
|
73 |
`-------------------------------------------------------------------*/ |
`-------------------------------------------------------------------*/ |
74 |
|
|
75 |
static bool |
static bool |
76 |
useful_production (int i, BSet N0) |
useful_production (int i, bitset N0) |
77 |
{ |
{ |
78 |
rule r; |
rule r; |
79 |
short n; |
short n; |
83 |
|
|
84 |
for (r = &ritem[rules[i].rhs]; *r >= 0; r++) |
for (r = &ritem[rules[i].rhs]; *r >= 0; r++) |
85 |
if (ISVAR (n = *r)) |
if (ISVAR (n = *r)) |
86 |
if (!BITISSET (N0, n - ntokens)) |
if (!bitset_test (N0, n - ntokens)) |
87 |
return FALSE; |
return FALSE; |
88 |
return TRUE; |
return TRUE; |
89 |
} |
} |
96 |
static void |
static void |
97 |
useless_nonterminals (void) |
useless_nonterminals (void) |
98 |
{ |
{ |
99 |
BSet Np, Ns; |
bitset Np, Ns; |
100 |
int i; |
int i; |
101 |
|
|
102 |
/* N is set as built. Np is set being built this iteration. P is |
/* N is set as built. Np is set being built this iteration. P is |
103 |
set of all productions which have a RHS all in N. */ |
set of all productions which have a RHS all in N. */ |
104 |
|
|
105 |
Np = XCALLOC (unsigned, WORDSIZE (nvars)); |
Np = bitset_create (nvars, BITSET_FIXED); |
106 |
|
bitset_zero (Np); |
107 |
|
|
108 |
|
|
109 |
/* The set being computed is a set of nonterminals which can derive |
/* The set being computed is a set of nonterminals which can derive |
110 |
the empty string or strings consisting of all terminals. At each |
the empty string or strings consisting of all terminals. At each |
124 |
|
|
125 |
while (1) |
while (1) |
126 |
{ |
{ |
127 |
for (i = WORDSIZE (nvars) - 1; i >= 0; i--) |
bitset_copy (Np, N); |
|
Np[i] = N[i]; |
|
128 |
for (i = 1; i <= nrules; i++) |
for (i = 1; i <= nrules; i++) |
129 |
{ |
{ |
130 |
if (!BITISSET (P, i)) |
if (!bitset_test (P, i)) |
131 |
{ |
{ |
132 |
if (useful_production (i, N)) |
if (useful_production (i, N)) |
133 |
{ |
{ |
134 |
SETBIT (Np, rules[i].lhs - ntokens); |
bitset_set (Np, rules[i].lhs - ntokens); |
135 |
SETBIT (P, i); |
bitset_set (P, i); |
136 |
} |
} |
137 |
} |
} |
138 |
} |
} |
139 |
if (bits_equal (N, Np, WORDSIZE (nvars))) |
if (bitset_equal_p (N, Np)) |
140 |
break; |
break; |
141 |
Ns = Np; |
Ns = Np; |
142 |
Np = N; |
Np = N; |
143 |
N = Ns; |
N = Ns; |
144 |
} |
} |
145 |
XFREE (N); |
bitset_free (N); |
146 |
N = Np; |
N = Np; |
147 |
} |
} |
148 |
|
|
150 |
static void |
static void |
151 |
inaccessable_symbols (void) |
inaccessable_symbols (void) |
152 |
{ |
{ |
153 |
BSet Vp, Vs, Pp; |
bitset Vp, Vs, Pp; |
154 |
int i; |
int i; |
155 |
short t; |
short t; |
156 |
rule r; |
rule r; |
178 |
terminals are printed (if running in verbose mode) so that the |
terminals are printed (if running in verbose mode) so that the |
179 |
user can know. */ |
user can know. */ |
180 |
|
|
181 |
Vp = XCALLOC (unsigned, WORDSIZE (nsyms)); |
Vp = bitset_create (nsyms, BITSET_FIXED); |
182 |
Pp = XCALLOC (unsigned, WORDSIZE (nrules + 1)); |
bitset_zero (Vp); |
183 |
|
Pp = bitset_create (nrules + 1, BITSET_FIXED); |
184 |
|
bitset_zero (Pp); |
185 |
|
|
186 |
/* If the start symbol isn't useful, then nothing will be useful. */ |
/* If the start symbol isn't useful, then nothing will be useful. */ |
187 |
if (BITISSET (N, start_symbol - ntokens)) |
if (bitset_test (N, start_symbol - ntokens)) |
188 |
{ |
{ |
189 |
SETBIT (V, start_symbol); |
bitset_set (V, start_symbol); |
190 |
|
|
191 |
while (1) |
while (1) |
192 |
{ |
{ |
193 |
for (i = WORDSIZE (nsyms) - 1; i >= 0; i--) |
bitset_copy (Vp, V); |
|
Vp[i] = V[i]; |
|
194 |
for (i = 1; i <= nrules; i++) |
for (i = 1; i <= nrules; i++) |
195 |
{ |
{ |
196 |
if (!BITISSET (Pp, i) |
if (!bitset_test (Pp, i) |
197 |
&& BITISSET (P, i) |
&& bitset_test (P, i) |
198 |
&& BITISSET (V, rules[i].lhs)) |
&& bitset_test (V, rules[i].lhs)) |
199 |
{ |
{ |
200 |
for (r = &ritem[rules[i].rhs]; *r >= 0; r++) |
for (r = &ritem[rules[i].rhs]; *r >= 0; r++) |
201 |
if (ISTOKEN (t = *r) || BITISSET (N, t - ntokens)) |
if (ISTOKEN (t = *r) || bitset_test (N, t - ntokens)) |
202 |
SETBIT (Vp, t); |
bitset_set (Vp, t); |
203 |
SETBIT (Pp, i); |
bitset_set (Pp, i); |
204 |
} |
} |
205 |
} |
} |
206 |
if (bits_equal (V, Vp, WORDSIZE (nsyms))) |
if (bitset_equal_p (V, Vp)) |
207 |
break; |
break; |
208 |
Vs = Vp; |
Vs = Vp; |
209 |
Vp = V; |
Vp = V; |
211 |
} |
} |
212 |
} |
} |
213 |
|
|
214 |
XFREE (V); |
bitset_free (V); |
215 |
V = Vp; |
V = Vp; |
216 |
|
|
217 |
/* Tokens 0, 1, and 2 are internal to Bison. Consider them useful. */ |
/* Tokens 0, 1, and 2 are internal to Bison. Consider them useful. */ |
218 |
SETBIT (V, 0); /* end-of-input token */ |
bitset_set (V, 0); /* end-of-input token */ |
219 |
SETBIT (V, 1); /* error token */ |
bitset_set (V, 1); /* error token */ |
220 |
SETBIT (V, 2); /* some undefined token */ |
bitset_set (V, 2); /* some undefined token */ |
221 |
|
|
222 |
XFREE (P); |
bitset_free (P); |
223 |
P = Pp; |
P = Pp; |
224 |
|
|
225 |
nuseful_productions = bits_size (P, WORDSIZE (nrules + 1)); |
nuseful_productions = bits_size (P); |
226 |
nuseless_productions = nrules - nuseful_productions; |
nuseless_productions = nrules - nuseful_productions; |
227 |
|
|
228 |
nuseful_nonterminals = 0; |
nuseful_nonterminals = 0; |
229 |
for (i = ntokens; i < nsyms; i++) |
for (i = ntokens; i < nsyms; i++) |
230 |
if (BITISSET (V, i)) |
if (bitset_test (V, i)) |
231 |
nuseful_nonterminals++; |
nuseful_nonterminals++; |
232 |
nuseless_nonterminals = nvars - nuseful_nonterminals; |
nuseless_nonterminals = nvars - nuseful_nonterminals; |
233 |
|
|
234 |
/* A token that was used in %prec should not be warned about. */ |
/* A token that was used in %prec should not be warned about. */ |
235 |
for (i = 1; i < nrules; i++) |
for (i = 1; i < nrules; i++) |
236 |
if (rules[i].precsym != 0) |
if (rules[i].precsym != 0) |
237 |
SETBIT (V1, rules[i].precsym); |
bitset_set (V1, rules[i].precsym); |
238 |
} |
} |
239 |
|
|
240 |
static void |
static void |
259 |
np = 0; |
np = 0; |
260 |
ni = 0; |
ni = 0; |
261 |
for (pn = 1; pn <= nrules; pn++) |
for (pn = 1; pn <= nrules; pn++) |
262 |
if (BITISSET (P, pn)) |
if (bitset_test (P, pn)) |
263 |
{ |
{ |
264 |
np++; |
np++; |
265 |
if (pn != np) |
if (pn != np) |
299 |
{ |
{ |
300 |
int pn; |
int pn; |
301 |
for (pn = 1; pn <= nrules; pn++) |
for (pn = 1; pn <= nrules; pn++) |
302 |
rules[pn].useful = BITISSET (P, pn); |
rules[pn].useful = bitset_test (P, pn); |
303 |
} |
} |
304 |
} |
} |
305 |
|
|
319 |
short *nontermmap = XCALLOC (short, nvars) - ntokens; |
short *nontermmap = XCALLOC (short, nvars) - ntokens; |
320 |
n = ntokens; |
n = ntokens; |
321 |
for (i = ntokens; i < nsyms; i++) |
for (i = ntokens; i < nsyms; i++) |
322 |
if (BITISSET (V, i)) |
if (bitset_test (V, i)) |
323 |
nontermmap[i] = n++; |
nontermmap[i] = n++; |
324 |
for (i = ntokens; i < nsyms; i++) |
for (i = ntokens; i < nsyms; i++) |
325 |
if (!BITISSET (V, i)) |
if (!bitset_test (V, i)) |
326 |
nontermmap[i] = n++; |
nontermmap[i] = n++; |
327 |
|
|
328 |
|
|
380 |
bool b = FALSE; |
bool b = FALSE; |
381 |
int i; |
int i; |
382 |
for (i = 0; i < ntokens; i++) |
for (i = 0; i < ntokens; i++) |
383 |
if (!BITISSET (V, i) && !BITISSET (V1, i)) |
if (!bitset_test (V, i) && !bitset_test (V1, i)) |
384 |
{ |
{ |
385 |
if (!b) |
if (!b) |
386 |
fprintf (out, "%s\n\n", _("Terminals which are not used:")); |
fprintf (out, "%s\n\n", _("Terminals which are not used:")); |
498 |
|
|
499 |
/* Allocate the global sets used to compute the reduced grammar */ |
/* Allocate the global sets used to compute the reduced grammar */ |
500 |
|
|
501 |
N = XCALLOC (unsigned, WORDSIZE (nvars)); |
N = bitset_create (nvars, BITSET_FIXED); |
502 |
P = XCALLOC (unsigned, WORDSIZE (nrules + 1)); |
bitset_zero (N); |
503 |
V = XCALLOC (unsigned, WORDSIZE (nsyms)); |
P = bitset_create (nrules + 1, BITSET_FIXED); |
504 |
V1 = XCALLOC (unsigned, WORDSIZE (nsyms)); |
bitset_zero (P); |
505 |
|
V = bitset_create (nsyms, BITSET_FIXED); |
506 |
|
bitset_zero (V); |
507 |
|
V1 = bitset_create (nsyms, BITSET_FIXED); |
508 |
|
bitset_zero (V1); |
509 |
|
|
510 |
useless_nonterminals (); |
useless_nonterminals (); |
511 |
inaccessable_symbols (); |
inaccessable_symbols (); |
517 |
|
|
518 |
reduce_print (); |
reduce_print (); |
519 |
|
|
520 |
if (!BITISSET (N, start_symbol - ntokens)) |
if (!bitset_test (N, start_symbol - ntokens)) |
521 |
fatal (_("Start symbol %s does not derive any sentence"), |
fatal (_("Start symbol %s does not derive any sentence"), |
522 |
symbols[start_symbol]->tag); |
symbols[start_symbol]->tag); |
523 |
|
|
543 |
void |
void |
544 |
reduce_free (void) |
reduce_free (void) |
545 |
{ |
{ |
546 |
XFREE (N); |
bitset_free (N); |
547 |
XFREE (V); |
bitset_free (V); |
548 |
XFREE (V1); |
bitset_free (V1); |
549 |
XFREE (P); |
bitset_free (P); |
550 |
} |
} |