Instead of mapping the LHS of unused rules to -1, keep the LHS

valid, but flag the rules as invalid.
* src/gram.h (rule_t): `useful' is a new member.
* src/print.c (print_grammar): Adjust.
* src/derives.c (set_derives): Likewise.
* src/reader.c (packgram, reduce_output): Likewise.
* src/reduce.c (reduce_grammar_tables): Likewise.
* tests/reduce.at (Underivable Rules, Useless Rules): New.
This commit is contained in:
Akim Demaille
2001-11-30 10:46:08 +00:00
parent d287d66a69
commit d39a6b7ca9
7 changed files with 131 additions and 30 deletions

View File

@@ -1,3 +1,15 @@
2001-11-30 Akim Demaille <akim@epita.fr>
Instead of mapping the LHS of unused rules to -1, keep the LHS
valid, but flag the rules as invalid.
* src/gram.h (rule_t): `useful' is a new member.
* src/print.c (print_grammar): Adjust.
* src/derives.c (set_derives): Likewise.
* src/reader.c (packgram, reduce_output): Likewise.
* src/reduce.c (reduce_grammar_tables): Likewise.
* tests/reduce.at (Underivable Rules, Useless Rules): New.
2001-11-30 Akim Demaille <akim@epita.fr> 2001-11-30 Akim Demaille <akim@epita.fr>
* src/reduce.c (reduce_output): Formatting changes. * src/reduce.c (reduce_output): Formatting changes.

View File

@@ -63,7 +63,6 @@ void
set_derives (void) set_derives (void)
{ {
int i; int i;
int lhs;
shorts *p; shorts *p;
short *q; short *q;
shorts **dset; shorts **dset;
@@ -74,16 +73,14 @@ set_derives (void)
p = delts; p = delts;
for (i = nrules; i > 0; i--) for (i = nrules; i > 0; i--)
{ if (rule_table[i].useful)
lhs = rule_table[i].lhs; {
if (lhs >= 0) int lhs = rule_table[i].lhs;
{ p->next = dset[lhs];
p->next = dset[lhs]; p->value = i;
p->value = i; dset[lhs] = p;
dset[lhs] = p; p++;
p++; }
}
}
derives = XCALLOC (short *, nvars) - ntokens; derives = XCALLOC (short *, nvars) - ntokens;
q = XCALLOC (short, nvars + nrules); q = XCALLOC (short, nvars + nrules);

View File

@@ -59,6 +59,8 @@
RULE_TABLE[R].line -- the line where R was defined. RULE_TABLE[R].line -- the line where R was defined.
RULE_TABLE[R].useful -- TRUE iff the rule is used.
The right hand side is stored as symbol numbers in a portion of The right hand side is stored as symbol numbers in a portion of
RITEM. RITEM.
@@ -119,6 +121,7 @@ typedef struct rule_s
short precsym; short precsym;
short assoc; short assoc;
short line; short line;
bool useful;
} rule_t; } rule_t;
extern struct rule_s *rule_table; extern struct rule_s *rule_table;

View File

@@ -216,7 +216,7 @@ print_grammar (FILE *out)
fprintf (out, " %s\n", _("Number, Line, Rule")); fprintf (out, " %s\n", _("Number, Line, Rule"));
for (i = 1; i <= nrules; i++) for (i = 1; i <= nrules; i++)
/* Don't print rules disabled in reduce_grammar_tables. */ /* Don't print rules disabled in reduce_grammar_tables. */
if (rule_table[i].lhs >= 0) if (rule_table[i].useful)
{ {
fprintf (out, _(" %3d %3d %s ->"), fprintf (out, _(" %3d %3d %s ->"),
i, rule_table[i].line, tags[rule_table[i].lhs]); i, rule_table[i].line, tags[rule_table[i].lhs]);

View File

@@ -1877,6 +1877,7 @@ packgram (void)
rule_table[ruleno].lhs = p->sym->value; rule_table[ruleno].lhs = p->sym->value;
rule_table[ruleno].rhs = itemno; rule_table[ruleno].rhs = itemno;
rule_table[ruleno].line = p->line; rule_table[ruleno].line = p->line;
rule_table[ruleno].useful = TRUE;
p = p->next; p = p->next;
while (p && p->sym) while (p && p->sym)

View File

@@ -310,20 +310,12 @@ reduce_grammar_tables (void)
} }
#endif /* 0 */ #endif /* 0 */
/* Disable useless productions, /* Disable useless productions. */
since they may contain useless nonterms
that would get mapped below to -1 and confuse everyone. */
if (nuseless_productions > 0) if (nuseless_productions > 0)
{ {
int pn; int pn;
for (pn = 1; pn <= nrules; pn++) for (pn = 1; pn <= nrules; pn++)
{ rule_table[pn].useful = BITISSET (P, pn);
if (!BITISSET (P, pn))
{
rule_table[pn].lhs = -1;
}
}
} }
} }
@@ -338,8 +330,8 @@ nonterminals_reduce (void)
int i, n; int i, n;
rule r; rule r;
/* Create a map of nonterminal number to new nonterminal number. -1 /* Map the nonterminals to their new index: useful first, useless
in the map means it was useless and is being eliminated. */ afterwards. Kept for later report. */
short *nontermmap = XCALLOC (short, nvars) - ntokens; short *nontermmap = XCALLOC (short, nvars) - ntokens;
n = ntokens; n = ntokens;
@@ -379,9 +371,7 @@ nonterminals_reduce (void)
for (i = 1; i <= nrules; i++) for (i = 1; i <= nrules; i++)
{ {
/* Ignore the rules disabled above. */ rule_table[i].lhs = nontermmap[rule_table[i].lhs];
if (rule_table[i].lhs >= 0)
rule_table[i].lhs = nontermmap[rule_table[i].lhs];
if (ISVAR (rule_table[i].precsym)) if (ISVAR (rule_table[i].precsym))
/* Can this happen? */ /* Can this happen? */
rule_table[i].precsym = nontermmap[rule_table[i].precsym]; rule_table[i].precsym = nontermmap[rule_table[i].precsym];
@@ -396,7 +386,7 @@ nonterminals_reduce (void)
nsyms -= nuseless_nonterminals; nsyms -= nuseless_nonterminals;
nvars -= nuseless_nonterminals; nvars -= nuseless_nonterminals;
free (&nontermmap[ntokens]); free (nontermmap + ntokens);
} }
@@ -436,11 +426,11 @@ reduce_output (FILE *out)
int i; int i;
fprintf (out, "%s\n\n", _("Useless rules:")); fprintf (out, "%s\n\n", _("Useless rules:"));
for (i = 1; i <= nrules; i++) for (i = 1; i <= nrules; i++)
if (!BITISSET (P, i)) if (!rule_table[i].useful)
{ {
rule r; rule r;
fprintf (out, "#%-4d ", i); fprintf (out, "#%-4d ", i);
fprintf (out, "%s :\t", tags[rule_table[i].lhs]); fprintf (out, "%s:", tags[rule_table[i].lhs]);
for (r = &ritem[rule_table[i].rhs]; *r >= 0; r++) for (r = &ritem[rule_table[i].rhs]; *r >= 0; r++)
fprintf (out, " %s", tags[*r]); fprintf (out, " %s", tags[*r]);
fputs (";\n", out); fputs (";\n", out);

View File

@@ -106,3 +106,101 @@ AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0,
]]) ]])
AT_CLEANUP AT_CLEANUP
## --------------- ##
## Useless Rules. ##
## --------------- ##
AT_SETUP([Useless Rules])
AT_DATA([[input.y]],
[[%verbose
%output="input.c"
%token useful
%%
exp: useful;
useless1: '1';
useless2: '2';
useless3: '3';
useless4: '4';
useless5: '5';
useless6: '6';
useless7: '7';
useless8: '8';
useless9: '9';
]])
AT_CHECK([[bison input.y]], 0, [],
[[input.y contains 9 useless nonterminals and 9 useless rules
]])
AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0,
[[Useless nonterminals:
useless1
useless2
useless3
useless4
useless5
useless6
useless7
useless8
useless9
Terminals which are not used:
'1'
'2'
'3'
'4'
'5'
'6'
'7'
'8'
'9'
Useless rules:
#2 useless1: '1';
#3 useless2: '2';
#4 useless3: '3';
#5 useless4: '4';
#6 useless5: '5';
#7 useless6: '6';
#8 useless7: '7';
#9 useless8: '8';
#10 useless9: '9';
]])
AT_CLEANUP
## ------------------- ##
## Underivable Rules. ##
## ------------------- ##
AT_SETUP([Underivable Rules])
AT_DATA([[input.y]],
[[%verbose
%output="input.c"
%token useful
%%
exp: useful | underivable;
underivable: indirection;
indirection: underivable;
]])
AT_CHECK([[bison input.y]], 0, [],
[[input.y contains 2 useless nonterminals and 3 useless rules
]])
AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0,
[[Useless nonterminals:
underivable
indirection
Useless rules:
#2 exp: underivable;
#3 underivable: indirection;
#4 indirection: underivable;
]])
AT_CLEANUP