reduced here, since anyway that computation doesn't work.
* src/gram.h, src/gram.h (rule_filter_t, rule_useful_p)
(rule_useless_p, rule_never_reduced_p): New.
(grammar_rules_partial_print): Use a filter instead of a range.
Display the title only if needed.
(grammar_rules_print): Adjust.
(grammar_rules_never_reduced_report): New.
* src/tables.c (action_row): Move the computation of rules never
reduced to...
(token_actions): here.
* src/main.c (main): Make the parser before making the report, so
that rules never reduced are computed.
Call grammar_rules_never_reduced_report.
* src/print.c (print_results): Report rules never reduced.
* tests/conflicts.at, tests/reduce.at: Adjust.
+2002-08-02 Akim Demaille <akim@epita.fr>
+
+ * src/conflicts.c (conflicts_output): Don't output rules never
+ reduced here, since anyway that computation doesn't work.
+ * src/gram.h, src/gram.h (rule_filter_t, rule_useful_p)
+ (rule_useless_p, rule_never_reduced_p): New.
+ (grammar_rules_partial_print): Use a filter instead of a range.
+ Display the title only if needed.
+ (grammar_rules_print): Adjust.
+ (grammar_rules_never_reduced_report): New.
+ * src/tables.c (action_row): Move the computation of rules never
+ reduced to...
+ (token_actions): here.
+ * src/main.c (main): Make the parser before making the report, so
+ that rules never reduced are computed.
+ Call grammar_rules_never_reduced_report.
+ * src/print.c (print_results): Report rules never reduced.
+ * tests/conflicts.at, tests/reduce.at: Adjust.
+
2002-08-01 Akim Demaille <akim@epita.fr>
Instead of attaching lookaheads and duplicating the rules being
conflicts_output (FILE *out)
{
bool printed_sth = FALSE;
- bool *used_rules = XCALLOC (bool, nrules);
state_number_t i;
for (i = 0; i < nstates; i++)
{
state_t *s = states[i];
- reductions_t *reds = s->reductions;
- int j;
- for (j = 0; j < reds->num; ++j)
- used_rules[reds->rules[j]->number] = TRUE;
if (conflicts[i])
{
fprintf (out, _("State %d contains "), i);
}
if (printed_sth)
fputs ("\n\n", out);
-
- for (i = 0; i < nstates; i++)
- {
- state_t *s = states[i];
- reductions_t *r = s->reductions;
- int j;
- for (j = 0; j < r->num; ++j)
- if (!used_rules[r->rules[j]->number])
- {
- LOCATION_PRINT (stderr, r->rules[j]->location);
- fprintf (stderr, ": %s: %s: ",
- _("warning"),
- _("rule never reduced because of conflicts"));
- rule_print (r->rules[j], stderr);
- }
- }
- free (used_rules);
}
/*--------------------------------------------------------.
int pure_parser = 0;
+/*--------------------------------------------------------------.
+| Return true IFF the rule has a `number' smaller than NRULES. |
+`--------------------------------------------------------------*/
+
+bool
+rule_useful_p (rule_t *r)
+{
+ return r->number < nrules;
+}
+
+
+/*-------------------------------------------------------------.
+| Return true IFF the rule has a `number' higher than NRULES. |
+`-------------------------------------------------------------*/
+
+bool
+rule_useless_p (rule_t *r)
+{
+ return r->number >= nrules;
+}
+
+
+/*--------------------------------------------------------------------.
+| Return true IFF the rule is not flagged as useful *and* is useful. |
+| In other words, it was discarded because of conflicts. |
+`--------------------------------------------------------------------*/
+
+bool
+rule_never_reduced_p (rule_t *r)
+{
+ return !r->useful && r->number < nrules;
+}
+
+
/*----------------------------------------------------------------.
| Print this RULE's number and lhs on OUT. If a PREVIOUS_LHS was |
| already displayed (by a previous call for another rule), avoid |
}
-/*----------------------------------------------------------------.
-| Print the grammar's rules numbers from BEGIN (inclusive) to END |
-| (exclusive) on OUT under TITLE. |
-`----------------------------------------------------------------*/
+/*-----------------------------------------------------------------.
+| Print the grammar's rules that match FILTER on OUT under TITLE. |
+`-----------------------------------------------------------------*/
void
grammar_rules_partial_print (FILE *out, const char *title,
- rule_number_t begin, rule_number_t end)
+ rule_filter_t filter)
{
int r;
+ bool first = TRUE;
symbol_t *previous_lhs = NULL;
/* rule # : LHS -> RHS */
- fprintf (out, "%s\n\n", title);
- for (r = begin; r < end; r++)
+ for (r = 0; r < nrules + nuseless_productions; r++)
{
- if (previous_lhs && previous_lhs != rules[r].lhs)
+ if (filter && !filter (&rules[r]))
+ continue;
+ if (first)
+ fprintf (out, "%s\n\n", title);
+ else if (previous_lhs && previous_lhs != rules[r].lhs)
fputc ('\n', out);
+ first = FALSE;
rule_lhs_print (&rules[r], previous_lhs, out);
rule_rhs_print (&rules[r], out);
previous_lhs = rules[r].lhs;
}
- fputs ("\n\n", out);
+ if (!first)
+ fputs ("\n\n", out);
}
void
grammar_rules_print (FILE *out)
{
- grammar_rules_partial_print (out, _("Grammar"), 0, nrules);
+ grammar_rules_partial_print (out, _("Grammar"), rule_useful_p);
}
}
+/*------------------------------------------------------------------.
+| Report on STDERR the rules that are not flagged USEFUL, using the |
+| MESSAGE (which can be `useless rule' when invoked after grammar |
+| reduction, or `never reduced' after conflicts were taken into |
+| account). |
+`------------------------------------------------------------------*/
+
+void
+grammar_rules_never_reduced_report (const char *message)
+{
+ rule_number_t r;
+ for (r = 0; r < nrules ; ++r)
+ if (!rules[r].useful)
+ {
+ LOCATION_PRINT (stderr, rules[r].location);
+ fprintf (stderr, ": %s: %s: ",
+ _("warning"), message);
+ rule_print (&rules[r], stderr);
+ }
+}
+
void
grammar_free (void)
{
extern struct rule_s *rules;
+/* A function that selects a rule. */
+typedef bool (*rule_filter_t) PARAMS ((rule_t *r));
+
+/* Return true IFF the rule has a `number' smaller than NRULES. */
+bool rule_useful_p PARAMS ((rule_t *r));
+
+/* Return true IFF the rule has a `number' higher than NRULES. */
+bool rule_useless_p PARAMS ((rule_t *r));
+
+/* Return true IFF the rule is not flagged as useful *and* is useful.
+ In other words, it was discarded because of conflicts. */
+bool rule_never_reduced_p PARAMS ((rule_t *r));
+
+/* Print this RULE's number and lhs on OUT. If a PREVIOUS_LHS was
+ already displayed (by a previous call for another rule), avoid
+ useless repetitions. */
+void rule_lhs_print PARAMS ((rule_t *rule, symbol_t *previous_lhs, FILE *out));
+
+/* Return the length of the RHS. */
+int rule_rhs_length PARAMS ((rule_t *rule));
+
+/* Print this RULE's RHS on OUT. */
+void rule_rhs_print PARAMS ((rule_t *rule, FILE *out));
+
+/* Print this RULE on OUT. */
+void rule_print PARAMS ((rule_t *rule, FILE *out));
+
+
+
+
/* Table of the symbols, indexed by the symbol number. */
extern symbol_t **symbols;
extern int max_user_token_number;
+
/* GLR_PARSER is nonzero if the input file says to use the GLR
(Generalized LR) parser, and to output some additional
information used by the GLR algorithm. */
extern int pure_parser;
-/* Print this RULE's number and lhs on OUT. If a PREVIOUS_LHS was
- already displayed (by a previous call for another rule), avoid
- useless repetitions. */
-void rule_lhs_print PARAMS ((rule_t *rule, symbol_t *previous_lhs, FILE *out));
-
-/* Return the length of the RHS. */
-int rule_rhs_length PARAMS ((rule_t *rule));
-
-/* Print this RULE's RHS on OUT. */
-void rule_rhs_print PARAMS ((rule_t *rule, FILE *out));
-
-/* Print this RULE on OUT. */
-void rule_print PARAMS ((rule_t *rule, FILE *out));
-
/* Dump RITEM for traces. */
void ritem_print PARAMS ((FILE *out));
/* Print the grammar's rules numbers from BEGIN (inclusive) to END
(exclusive) on OUT under TITLE. */
void grammar_rules_partial_print PARAMS ((FILE *out, const char *title,
- rule_number_t begin,
- rule_number_t end));
+ rule_filter_t filter));
/* Print the grammar's rules on OUT. */
void grammar_rules_print PARAMS ((FILE *out));
/* Dump the grammar. */
void grammar_dump PARAMS ((FILE *out, const char *title));
+/* Report on STDERR the rules that are not flagged USEFUL, using the
+ MESSAGE (which can be `useless rule' when invoked after grammar
+ reduction, or `never reduced' after conflicts were taken into
+ account). */
+void grammar_rules_never_reduced_report PARAMS ((const char *message));
+
/* Free the packed grammar. */
void grammar_free PARAMS ((void));
conflicts_print ();
timevar_pop (TV_CONFLICTS);
+ /* Compute the parser tables. */
+ timevar_push (TV_ACTIONS);
+ tables_generate ();
+ timevar_pop (TV_ACTIONS);
+
+ grammar_rules_never_reduced_report
+ (_("rule never reduced because of conflicts"));
+
/* Output file names. */
compute_output_file_names ();
timevar_pop (TV_REPORT);
}
- /* Stop if there were errors, to avoid trashing previous output
- files. */
- if (complain_message_count)
- exit (1);
-
/* Output the VCG graph. */
if (graph_flag)
{
timevar_pop (TV_GRAPH);
}
- /* Compute the parser tables. */
- timevar_push (TV_ACTIONS);
- tables_generate ();
- timevar_pop (TV_ACTIONS);
+ /* Stop if there were errors, to avoid trashing previous output
+ files. */
+ if (complain_message_count)
+ exit (1);
/* Lookaheads are no longer needed. */
timevar_push (TV_FREE);
FILE *out = xfopen (spec_verbose_file, "w");
reduce_output (out);
+ grammar_rules_partial_print (out,
+ _("Rules never reduced"), rule_never_reduced_p);
conflicts_output (out);
print_grammar (out);
{
rule_number_t r;
for (r = 0; r < nrules; r++)
- {
- rules[r].useful = bitset_test (P, r);
- if (!rules[r].useful)
- {
- LOCATION_PRINT (stderr, rules[r].location);
- fprintf (stderr, ": %s: %s: ", _("warning"), _("useless rule"));
- rule_print (&rules[r], stderr);
- }
- }
+ rules[r].useful = bitset_test (P, r);
+ grammar_rules_never_reduced_report (_("useless rule"));
}
/* Map the nonterminals to their new index: useful first, useless
if (nuseless_nonterminals > 0)
{
int i;
- fprintf (out, "%s\n\n", _("Useless nonterminals:"));
+ fprintf (out, "%s\n\n", _("Useless nonterminals"));
for (i = 0; i < nuseless_nonterminals; ++i)
fprintf (out, " %s\n", symbols[nsyms + i]->tag);
fputs ("\n\n", out);
if (!bitset_test (V, i) && !bitset_test (V1, i))
{
if (!b)
- fprintf (out, "%s\n\n", _("Terminals which are not used:"));
+ fprintf (out, "%s\n\n", _("Terminals which are not used"));
b = TRUE;
fprintf (out, " %s\n", symbols[i]->tag);
}
if (nuseless_productions > 0)
grammar_rules_partial_print (out, _("Useless rules"),
- nrules,
- nrules + nuseless_productions);
+ rule_useless_p);
}
\f
}
}
- /* Find the rules which are reduced. */
- if (!glr_parser)
- {
- for (i = 0; i < ntokens; i++)
- if (actrow[i] < 0 && actrow[i] != ACTION_MIN)
- rules[item_number_as_rule_number (actrow[i])].useful = TRUE;
- if (default_rule)
- default_rule->useful = TRUE;
- }
-
/* If have no default rule, the default is an error.
So replace any action which says "error" with "use default". */
token_actions (void)
{
state_number_t i;
+ symbol_number_t j;
rule_number_t r;
+
int nconflict = conflicts_total_count ();
yydefact = XCALLOC (rule_number_t, nstates);
actrow = XCALLOC (action_t, ntokens);
conflrow = XCALLOC (unsigned int, ntokens);
- /* Now that the parser was computed, we can find which rules are
- really reduced, and which are not because of SR or RR conflicts.
- */
+ /* Find the rules which are reduced. */
if (!glr_parser)
for (r = 0; r < nrules; ++r)
rules[r].useful = FALSE;
rule_t *default_rule = action_row (states[i]);
yydefact[i] = default_rule ? default_rule->number + 1 : 0;
save_row (i);
- }
- if (!glr_parser)
- for (r = 0; r < nrules ; ++r)
- if (!rules[r].useful)
+ /* Now that the parser was computed, we can find which rules are
+ really reduced, and which are not because of SR or RR
+ conflicts. */
+ if (!glr_parser)
{
- LOCATION_PRINT (stderr, rules[r].location);
- fprintf (stderr, ": %s: %s: ",
- _("warning"), _("rule never reduced because of conflicts"));
- rule_print (&rules[r], stderr);
+ for (j = 0; j < ntokens; ++j)
+ if (actrow[j] < 0 && actrow[j] != ACTION_MIN)
+ rules[item_number_as_rule_number (actrow[j])].useful = TRUE;
+ if (yydefact[i])
+ rules[yydefact[i] - 1].useful = TRUE;
}
+ }
free (actrow);
free (conflrow);
# Check the contents of the report.
AT_CHECK([cat input.output], [],
-[[State 1 contains 1 reduce/reduce conflict.
+[[Rules never reduced
+
+ 4 id: '0'
+
+
+State 1 contains 1 reduce/reduce conflict.
Grammar
AT_CHECK([[bison input.y]])
AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0,
-[[Terminals which are not used:
+[[Terminals which are not used
useless1
useless2
useless3
]])
AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0,
-[[Useless nonterminals:
+[[Useless nonterminals
useless1
useless2
useless3
]])
AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0,
-[[Useless nonterminals:
+[[Useless nonterminals
useless1
useless2
useless3
useless7
useless8
useless9
-Terminals which are not used:
+Terminals which are not used
'1'
'2'
'3'
]])
AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' not-reduced.output]], 0,
-[[Useless nonterminals:
+[[Useless nonterminals
not_reachable
non_productive
-Terminals which are not used:
+Terminals which are not used
useless_token
Useless rules
2 exp: non_productive
]])
AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0,
-[[Useless nonterminals:
+[[Useless nonterminals
underivable
indirection
Useless rules