From: Akim Demaille Date: Sat, 15 Jun 2002 18:23:12 +0000 (+0000) Subject: Copy BYacc's nice way to report the grammar. X-Git-Tag: BISON-1_49b~170 X-Git-Url: https://git.saurik.com/bison.git/commitdiff_plain/6b98e4b5636203b60c2a43ddaa988562616b4c69?hp=ee000ba4fcd5b051bef4476341a7fdffbddf8ad3 Copy BYacc's nice way to report the grammar. * src/gram.h, src/gram.c (grammar_rhs_print, grammar_rules_print): New. Don't print the rules' location, it is confusing and useless. (rule_print): Use grammar_rhs_print. * src/print.c (print_grammar): Use grammar_rules_print. --- diff --git a/ChangeLog b/ChangeLog index 27a927b0..4995682a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +2002-06-15 Akim Demaille + + Copy BYacc's nice way to report the grammar. + + * src/gram.h, src/gram.c (grammar_rhs_print, grammar_rules_print): + New. + Don't print the rules' location, it is confusing and useless. + (rule_print): Use grammar_rhs_print. + * src/print.c (print_grammar): Use grammar_rules_print. + + +2002-06-15 Akim Demaille + + Complete and rationalize `useless thing' warnings. + + * src/symtab.h, src/symtab.c (symbol_tag_get, symbol_tag_get_n) + (symbol_tag_print): New. + Use them everywhere in place of accessing directly the tag member. + * src/gram.h, src/gram.c (rule_print): New. + Use it where a rule used to be printed `by hand'. + * src/reduce.c (nonterminals_reduce): Report the use nonterminals. + (reduce_grammar_tables): Report the useless rules. + (reduce_print): Useless things are a warning, not an error. + Report it as such. + * tests/reduce.at (Useless Nonterminals, Useless Rules): + (Reduced Automaton, Underivable Rules): Adjust. + * tests/regression.at (Web2c Report, Web2c Report): Adjust. + * tests/conflicts.at (Unresolved SR Conflicts) + (Solved SR Conflicts): Adjust. + + 2002-06-15 Akim Demaille Let symbols have a location. diff --git a/NEWS b/NEWS index 64258f23..0dc40542 100644 --- a/NEWS +++ b/NEWS @@ -42,6 +42,9 @@ Changes in version 1.49b: Before, Bison reported the useless rules, but, although not used, included them in the parsers. They are now actually removed. +* Useless rules, useless nonterminals + They are now reported, as a warning, with their locations. + * Incorrect `Token not used' On a grammar such as diff --git a/src/LR0.c b/src/LR0.c index efe9589a..95200d53 100644 --- a/src/LR0.c +++ b/src/LR0.c @@ -191,8 +191,7 @@ new_state (symbol_number_t symbol, size_t core_size, item_number_t *core) if (trace_flag) fprintf (stderr, "Entering new_state, state = %d, symbol = %d (%s)\n", - nstates, symbol, quotearg_style (escape_quoting_style, - symbols[symbol]->tag)); + nstates, symbol, symbol_tag_get (symbols[symbol])); if (nstates >= SHRT_MAX) fatal (_("too many states (max %d)"), SHRT_MAX); @@ -237,8 +236,8 @@ get_state (symbol_number_t symbol, size_t core_size, item_number_t *core) if (trace_flag) fprintf (stderr, "Entering get_state, state = %d, symbol = %d (%s)\n", - this_state->number, symbol, quotearg_style (escape_quoting_style, - symbols[symbol]->tag)); + this_state->number, symbol, + symbol_tag_get (symbols[symbol])); /* Add up the target state's active item numbers to get a hash key. */ @@ -424,8 +423,7 @@ generate_states (void) if (trace_flag) fprintf (stderr, "Processing state %d (reached by %s)\n", this_state->number, - quotearg_style (escape_quoting_style, - symbols[this_state->accessing_symbol]->tag)); + symbol_tag_get (symbols[this_state->accessing_symbol])); /* Set up ruleset and itemset for the transitions out of this state. ruleset gets a 1 bit for each rule that could reduce now. itemset gets a vector of all the items that could be diff --git a/src/closure.c b/src/closure.c index 928b6867..ea64250e 100644 --- a/src/closure.c +++ b/src/closure.c @@ -59,8 +59,7 @@ print_closure (const char *title, item_number_t *array, size_t size) item_number_t *rp; fprintf (stderr, " %2d: .", array[i]); for (rp = &ritem[array[i]]; *rp >= 0; ++rp) - fprintf (stderr, " %s", - quotearg_style (escape_quoting_style, symbols[*rp]->tag)); + fprintf (stderr, " %s", symbol_tag_get (symbols[*rp])); fprintf (stderr, " (rule %d)\n", -*rp - 1); } fputs ("\n\n", stderr); @@ -75,13 +74,11 @@ print_firsts (void) fprintf (stderr, "FIRSTS\n"); for (i = ntokens; i < nsyms; i++) { - fprintf (stderr, "\t%s firsts\n", - quotearg_style (escape_quoting_style, symbols[i]->tag)); + fprintf (stderr, "\t%s firsts\n", symbol_tag_get (symbols[i])); for (j = 0; j < nvars; j++) if (bitset_test (FIRSTS (i), j)) fprintf (stderr, "\t\t%s\n", - quotearg_style (escape_quoting_style, - symbols[j + ntokens]->tag)); + symbol_tag_get (symbols[j + ntokens])); } fprintf (stderr, "\n\n"); } @@ -95,17 +92,14 @@ print_fderives (void) fprintf (stderr, "FDERIVES\n"); for (i = ntokens; i < nsyms; i++) { - fprintf (stderr, "\t%s derives\n", - quotearg_style (escape_quoting_style, symbols[i]->tag)); + fprintf (stderr, "\t%s derives\n", symbol_tag_get (symbols[i])); for (j = 0; j < nrules + 1; j++) if (bitset_test (FDERIVES (i), j)) { item_number_t *rhsp; fprintf (stderr, "\t\t%d:", j - 1); for (rhsp = rules[j].rhs; *rhsp >= 0; ++rhsp) - fprintf (stderr, " %s", - quotearg_style (escape_quoting_style, - symbols[*rhsp]->tag)); + fprintf (stderr, " %s", symbol_tag_get (symbols[*rhsp])); fputc ('\n', stderr); } } diff --git a/src/gram.c b/src/gram.c index 90a0b527..a1a06308 100644 --- a/src/gram.c +++ b/src/gram.c @@ -26,7 +26,7 @@ #include "reduce.h" #include "reader.h" -/* comments for these variables are in gram.h */ +/* Comments for these variables are in gram.h. */ item_number_t *ritem = NULL; unsigned int nritems = 0; @@ -61,6 +61,39 @@ rule_rhs_length (rule_t *rule) } +/*-------------------------------. +| Print this RULE's RHS on OUT. | +`-------------------------------*/ + +void +rule_rhs_print (rule_t *rule, FILE *out) +{ + if (*rule->rhs >= 0) + { + item_number_t *r; + for (r = rule->rhs; *r >= 0; r++) + fprintf (out, " %s", symbol_tag_get (symbols[*r])); + fputc ('\n', out); + } + else + { + fprintf (out, " /* %s */\n", _("empty")); + } +} + + +/*-------------------------. +| Print this RULE on OUT. | +`-------------------------*/ + +void +rule_print (rule_t *rule, FILE *out) +{ + fprintf (out, "%s:", symbol_tag_get (rule->lhs)); + rule_rhs_print (rule, out); +} + + /*------------------------. | Dump RITEM for traces. | `------------------------*/ @@ -72,8 +105,7 @@ ritem_print (FILE *out) fputs ("RITEM\n", out); for (i = 0; i < nritems; ++i) if (ritem[i] >= 0) - fprintf (out, " %s", quotearg_style (escape_quoting_style, - symbols[ritem[i]]->tag)); + fprintf (out, " %s", symbol_tag_get (symbols[ritem[i]])); else fprintf (out, " (rule %d)\n", -ritem[i] - 1); fputs ("\n\n", out); @@ -101,6 +133,46 @@ ritem_longest_rhs (void) } +/*-----------------------------------. +| Print the grammar's rules on OUT. | +`-----------------------------------*/ + +static inline void +blanks_print (unsigned n, FILE *out) +{ + for (/* Nothing*/; n > 0; --n) + fputc (' ', out); +} + +void +grammar_rules_print (FILE *out) +{ + int r; + symbol_t *last_lhs = NULL; + + /* rule # : LHS -> RHS */ + fprintf (out, "%s\n\n", _("Grammar")); + for (r = 1; r < nrules + 1; r++) + { + if (last_lhs && last_lhs != rules[r].lhs) + fputc ('\n', out); + + fprintf (out, " %3d ", r - 1); + if (last_lhs != rules[r].lhs) + { + last_lhs = rules[r].lhs; + fprintf (out, "%s:", symbol_tag_get (last_lhs)); + } + else + { + blanks_print (strlen (symbol_tag_get (last_lhs)), out); + fputc ('|', out); + } + rule_rhs_print (&rules[r], out); + } + fputs ("\n\n", out); +} + /*-------------------. | Dump the grammar. | `-------------------*/ @@ -121,7 +193,7 @@ grammar_dump (FILE *out, const char *title) fprintf (out, "%5d %5d %5d %s\n", i, symbols[i]->prec, symbols[i]->assoc, - quotearg_style (escape_quoting_style, symbols[i]->tag)); + symbol_tag_get (symbols[i])); fprintf (out, "\n\n"); fprintf (out, "Rules\n-----\n\n"); fprintf (out, "Num (Prec, Assoc, Useful, Ritem Range) Lhs -> Rhs (Ritem range) [Num]\n"); @@ -148,12 +220,8 @@ grammar_dump (FILE *out, const char *title) fprintf (out, "Rules interpreted\n-----------------\n\n"); for (i = 1; i < nrules + nuseless_productions + 1; i++) { - fprintf (out, "%-5d %s :", - i, quotearg_style (escape_quoting_style, rules[i].lhs->tag)); - for (r = rules[i].rhs; *r >= 0; r++) - fprintf (out, " %s", - quotearg_style (escape_quoting_style, symbols[*r]->tag)); - fputc ('\n', out); + fprintf (out, "%-5d ", i); + rule_print (&rules[i], out); } fprintf (out, "\n\n"); } diff --git a/src/gram.h b/src/gram.h index ff43ab8f..962b9adb 100644 --- a/src/gram.h +++ b/src/gram.h @@ -168,15 +168,24 @@ extern int max_user_token_number; extern int pure_parser; -/* Report the length of the RHS. */ +/* 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)); /* Return the size of the longest rule RHS. */ size_t ritem_longest_rhs PARAMS ((void)); +/* 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)); diff --git a/src/lalr.c b/src/lalr.c index f3f37a73..dfc06bc9 100644 --- a/src/lalr.c +++ b/src/lalr.c @@ -565,7 +565,7 @@ lookaheads_print (FILE *out) for (k = 0; k < ntokens; ++k) if (bitset_test (LA[states[i]->lookaheadsp + j], k)) fprintf (out, " on %d (%s) -> rule %d\n", - k, quotearg_style (escape_quoting_style, symbols[k]->tag), + k, symbol_tag_get (symbols[k]), LArule[states[i]->lookaheadsp + j]->number - 1); } fprintf (out, "Lookaheads: END\n"); diff --git a/src/output.c b/src/output.c index 832f4ed9..7ee3214c 100644 --- a/src/output.c +++ b/src/output.c @@ -235,11 +235,11 @@ prepare_tokens (void) int j = 0; for (i = 0; i < nsyms; i++) { - /* Be sure not to use twice the same quotearg slot. */ + /* Be sure not to use twice the same QUOTEARG slot: + SYMBOL_TAG_GET uses slot 0. */ const char *cp = quotearg_n_style (1, c_quoting_style, - quotearg_style (escape_quoting_style, - symbols[i]->tag)); + symbol_tag_get (symbols[i])); /* Width of the next token, including the two quotes, the coma and the space. */ int strsize = strlen (cp) + 2; diff --git a/src/print.c b/src/print.c index bcf71cc6..280ac8d8 100644 --- a/src/print.c +++ b/src/print.c @@ -47,19 +47,6 @@ print_token (int extnum, int token) } #endif -static inline const char * -escape (const char *s) -{ - return quotearg_n_style (1, escape_quoting_style, s); -} - -/* Be cautious not to use twice the same slot in a single expression. */ -static inline const char * -escape2 (const char *s) -{ - return quotearg_n_style (2, escape_quoting_style, s); -} - /*--------------------------------. | Report information on a state. | @@ -94,15 +81,15 @@ print_core (FILE *out, state_t *state) sp++; rule = -(*sp); - fprintf (out, " %s -> ", escape (rules[rule].lhs->tag)); + fprintf (out, " %s -> ", symbol_tag_get (rules[rule].lhs)); for (sp = rules[rule].rhs; sp < sp1; sp++) - fprintf (out, "%s ", escape (symbols[*sp]->tag)); + fprintf (out, "%s ", symbol_tag_get (symbols[*sp])); fputc ('.', out); for (/* Nothing */; *sp >= 0; ++sp) - fprintf (out, " %s", escape (symbols[*sp]->tag)); + fprintf (out, " %s", symbol_tag_get (symbols[*sp])); /* Display the lookaheads? */ if (report_flag & report_lookaheads) @@ -123,8 +110,7 @@ print_core (FILE *out, state_t *state) if (bitset_test (LA[state->lookaheadsp + j], k) && LArule[state->lookaheadsp + j]->number == rule) fprintf (out, "%s%s", - quotearg_style (escape_quoting_style, - symbols[k]->tag), + symbol_tag_get (symbols[k]), --nlookaheads ? ", " : ""); fprintf (out, "]"); } @@ -152,7 +138,7 @@ print_shifts (FILE *out, state_t *state) symbol_number_t symbol = states[state1]->accessing_symbol; fprintf (out, _(" %-4s\tshift, and go to state %d\n"), - escape (symbols[symbol]->tag), state1); + symbol_tag_get (symbols[symbol]), state1); } if (i > 0) @@ -169,7 +155,7 @@ print_errs (FILE *out, state_t *state) for (i = 0; i < errp->nerrs; ++i) if (errp->errs[i]) fprintf (out, _(" %-4s\terror (nonassociative)\n"), - escape (symbols[errp->errs[i]]->tag)); + symbol_tag_get (symbols[errp->errs[i]])); if (i > 0) fputc ('\n', out); @@ -193,7 +179,7 @@ print_gotos (FILE *out, state_t *state) int state1 = shiftp->shifts[i]; symbol_number_t symbol = states[state1]->accessing_symbol; fprintf (out, _(" %-4s\tgo to state %d\n"), - escape (symbols[symbol]->tag), state1); + symbol_tag_get (symbols[symbol]), state1); } fputc ('\n', out); @@ -217,7 +203,7 @@ print_reductions (FILE *out, state_t *state) int rule = redp->rules[0]; symbol_number_t symbol = rules[rule].lhs->number; fprintf (out, _(" $default\treduce using rule %d (%s)\n\n"), - rule - 1, escape (symbols[symbol]->tag)); + rule - 1, symbol_tag_get (symbols[symbol])); return; } @@ -246,13 +232,13 @@ print_reductions (FILE *out, state_t *state) for (i = 0; i < ntokens; i++) if (bitset_test (lookaheadset, i)) fprintf (out, _(" %-4s\t[reduce using rule %d (%s)]\n"), - escape (symbols[i]->tag), + symbol_tag_get (symbols[i]), default_rule->number - 1, - escape2 (default_rule->lhs->tag)); + symbol_tag_get_n (default_rule->lhs, 1)); fprintf (out, _(" $default\treduce using rule %d (%s)\n\n"), default_rule->number - 1, - escape (default_rule->lhs->tag)); + symbol_tag_get (default_rule->lhs)); } else if (state->nlookaheads >= 1) { @@ -302,9 +288,9 @@ print_reductions (FILE *out, state_t *state) if (state->lookaheadsp + j != default_LA) fprintf (out, _(" %-4s\treduce using rule %d (%s)\n"), - escape (symbols[i]->tag), + symbol_tag_get (symbols[i]), LArule[state->lookaheadsp + j]->number - 1, - escape2 (LArule[state->lookaheadsp + j]->lhs->tag)); + symbol_tag_get_n (LArule[state->lookaheadsp + j]->lhs, 1)); else defaulted = 1; @@ -315,15 +301,15 @@ print_reductions (FILE *out, state_t *state) if (defaulted) fprintf (out, _(" %-4s\treduce using rule %d (%s)\n"), - escape (symbols[i]->tag), + symbol_tag_get (symbols[i]), LArule[default_LA]->number - 1, - escape2 (LArule[default_LA]->lhs->tag)); + symbol_tag_get_n (LArule[default_LA]->lhs, 1)); defaulted = 0; fprintf (out, _(" %-4s\t[reduce using rule %d (%s)]\n"), - escape (symbols[i]->tag), + symbol_tag_get (symbols[i]), LArule[state->lookaheadsp + j]->number - 1, - escape2 (LArule[state->lookaheadsp + j]->lhs->tag)); + symbol_tag_get_n (LArule[state->lookaheadsp + j]->lhs, 1)); } } } @@ -331,7 +317,7 @@ print_reductions (FILE *out, state_t *state) if (default_LA >= 0) fprintf (out, _(" $default\treduce using rule %d (%s)\n"), default_rule->number - 1, - escape (default_rule->lhs->tag)); + symbol_tag_get (default_rule->lhs)); } } @@ -389,47 +375,31 @@ static void print_grammar (FILE *out) { symbol_number_t i; - int j; item_number_t *rule; char buffer[90]; int column = 0; - /* rule # : LHS -> RHS */ - fprintf (out, "%s\n\n", _("Grammar")); - fprintf (out, " %s\n", _("Number, Line, Rule")); - for (j = 1; j < nrules + 1; j++) - { - fprintf (out, " %3d %3d %s ->", - j - 1, rules[j].location.first_line, - escape (rules[j].lhs->tag)); - rule = rules[j].rhs; - if (*rule >= 0) - while (*rule >= 0) - fprintf (out, " %s", escape (symbols[*rule++]->tag)); - else - fprintf (out, " /* %s */", _("empty")); - fputc ('\n', out); - } - fputs ("\n\n", out); - + grammar_rules_print (out); /* TERMINAL (type #) : rule #s terminal is on RHS */ fprintf (out, "%s\n\n", _("Terminals, with rules where they appear")); for (i = 0; i < max_user_token_number + 1; i++) if (token_translations[i] != undeftoken->number) { + const char *tag = symbol_tag_get (symbols[token_translations[i]]); + int r; buffer[0] = 0; - column = strlen (escape (symbols[token_translations[i]]->tag)); - fputs (escape (symbols[token_translations[i]]->tag), out); + column = strlen (tag); + fputs (tag, out); END_TEST (50); sprintf (buffer, " (%d)", i); - for (j = 1; j < nrules + 1; j++) - for (rule = rules[j].rhs; *rule >= 0; rule++) + for (r = 1; r < nrules + 1; r++) + for (rule = rules[r].rhs; *rule >= 0; rule++) if (item_number_as_symbol_number (*rule) == token_translations[i]) { END_TEST (65); - sprintf (buffer + strlen (buffer), " %d", j - 1); + sprintf (buffer + strlen (buffer), " %d", r - 1); break; } fprintf (out, "%s\n", buffer); @@ -441,12 +411,14 @@ print_grammar (FILE *out) for (i = ntokens; i < nsyms; i++) { int left_count = 0, right_count = 0; + int r; + const char *tag = symbol_tag_get (symbols[i]); - for (j = 1; j < nrules + 1; j++) + for (r = 1; r < nrules + 1; r++) { - if (rules[j].lhs->number == i) + if (rules[r].lhs->number == i) left_count++; - for (rule = rules[j].rhs; *rule >= 0; rule++) + for (rule = rules[r].rhs; *rule >= 0; rule++) if (item_number_as_symbol_number (*rule) == i) { right_count++; @@ -455,8 +427,8 @@ print_grammar (FILE *out) } buffer[0] = 0; - fputs (escape (symbols[i]->tag), out); - column = strlen (escape (symbols[i]->tag)); + fputs (tag, out); + column = strlen (tag); sprintf (buffer, " (%d)", i); END_TEST (0); @@ -465,11 +437,11 @@ print_grammar (FILE *out) END_TEST (50); sprintf (buffer + strlen (buffer), _(" on left:")); - for (j = 1; j < nrules + 1; j++) + for (r = 1; r < nrules + 1; r++) { END_TEST (65); - if (rules[j].lhs->number == i) - sprintf (buffer + strlen (buffer), " %d", j - 1); + if (rules[r].lhs->number == i) + sprintf (buffer + strlen (buffer), " %d", r - 1); } } @@ -479,13 +451,13 @@ print_grammar (FILE *out) sprintf (buffer + strlen (buffer), ","); END_TEST (50); sprintf (buffer + strlen (buffer), _(" on right:")); - for (j = 1; j < nrules + 1; j++) + for (r = 1; r < nrules + 1; r++) { - for (rule = rules[j].rhs; *rule >= 0; rule++) + for (rule = rules[r].rhs; *rule >= 0; rule++) if (item_number_as_symbol_number (*rule) == i) { END_TEST (65); - sprintf (buffer + strlen (buffer), " %d", j - 1); + sprintf (buffer + strlen (buffer), " %d", r - 1); break; } } diff --git a/src/print_graph.c b/src/print_graph.c index 6cd92ec9..49acaa7e 100644 --- a/src/print_graph.c +++ b/src/print_graph.c @@ -38,14 +38,11 @@ static graph_t graph; static FILE *fgraph = NULL; -static inline const char * -escape (const char *s) -{ - return quotearg_n_style (1, escape_quoting_style, s); -} +/*----------------------------. +| Construct the node labels. | +`----------------------------*/ -/* This part will construct the label of nodes. */ static void print_core (struct obstack *oout, state_t *state) { @@ -78,15 +75,15 @@ print_core (struct obstack *oout, state_t *state) if (i) obstack_1grow (oout, '\n'); obstack_fgrow1 (oout, " %s -> ", - escape (rules[rule].lhs->tag)); + symbol_tag_get (rules[rule].lhs)); for (sp = rules[rule].rhs; sp < sp1; sp++) - obstack_fgrow1 (oout, "%s ", escape (symbols[*sp]->tag)); + obstack_fgrow1 (oout, "%s ", symbol_tag_get (symbols[*sp])); obstack_1grow (oout, '.'); for (/* Nothing */; *sp >= 0; ++sp) - obstack_fgrow1 (oout, " %s", escape (symbols[*sp]->tag)); + obstack_fgrow1 (oout, " %s", symbol_tag_get (symbols[*sp])); /* Experimental feature: display the lookaheads. */ if (trace_flag && state->nlookaheads) @@ -107,8 +104,7 @@ print_core (struct obstack *oout, state_t *state) if (bitset_test (LA[state->lookaheadsp + j], k) && LArule[state->lookaheadsp + j]->number == rule) obstack_fgrow2 (oout, "%s%s", - quotearg_style (escape_quoting_style, - symbols[k]->tag), + symbol_tag_get (symbols[k]), --nlookaheads ? ", " : ""); obstack_sgrow (oout, "]"); } @@ -156,7 +152,7 @@ print_actions (state_t *state, const char *node_name) edge.color = red; else edge.color = SHIFT_IS_SHIFT(shiftp, i) ? blue : green; - edge.label = escape (symbols[symbol]->tag); + edge.label = symbol_tag_get (symbols[symbol]); output_edge (&edge, fgraph); close_edge (fgraph); } diff --git a/src/reduce.c b/src/reduce.c index 59afff78..2319b60b 100644 --- a/src/reduce.c +++ b/src/reduce.c @@ -227,11 +227,19 @@ inaccessable_symbols (void) static void reduce_grammar_tables (void) { - /* Flag useless productions. */ + /* Report and flag useless productions. */ { - int pn; - for (pn = 1; pn < nrules + 1; pn++) - rules[pn].useful = bitset_test (P, pn); + int r; + for (r = 1; r < nrules + 1; 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); + } + } } /* Map the nonterminals to their new index: useful first, useless @@ -290,7 +298,13 @@ nonterminals_reduce (void) nontermmap[i] = n++; for (i = ntokens; i < nsyms; i++) if (!bitset_test (V, i)) - nontermmap[i] = n++; + { + nontermmap[i] = n++; + LOCATION_PRINT (stderr, symbols[i]->location); + fprintf (stderr, ": %s: %s: %s\n", + _("warning"), _("useless nonterminal"), + symbol_tag_get (symbols[i])); + } /* Shuffle elements of tables indexed by symbol number. */ @@ -337,8 +351,7 @@ reduce_output (FILE *out) int i; fprintf (out, "%s\n\n", _("Useless nonterminals:")); for (i = 0; i < nuseless_nonterminals; ++i) - fprintf (out, " %s\n", quotearg_style (escape_quoting_style, - symbols[nsyms + i]->tag)); + fprintf (out, " %s\n", symbol_tag_get (symbols[nsyms + i])); fputs ("\n\n", out); } @@ -351,8 +364,7 @@ reduce_output (FILE *out) if (!b) fprintf (out, "%s\n\n", _("Terminals which are not used:")); b = TRUE; - fprintf (out, " %s\n", quotearg_style (escape_quoting_style, - symbols[i]->tag)); + fprintf (out, " %s\n", symbol_tag_get (symbols[i])); } if (b) fputs ("\n\n", out); @@ -366,11 +378,9 @@ reduce_output (FILE *out) { item_number_t *r; fprintf (out, "#%-4d ", rules[i].user_number - 1); - fprintf (out, "%s:", quotearg_style (escape_quoting_style, - rules[i].lhs->tag)); + fprintf (out, "%s:", symbol_tag_get (rules[i].lhs)); for (r = rules[i].rhs; *r >= 0; r++) - fprintf (out, " %s", quotearg_style (escape_quoting_style, - symbols[*r]->tag)); + fprintf (out, " %s", symbol_tag_get (symbols[*r])); fputs (";\n", out); } fputs ("\n\n", out); @@ -394,7 +404,7 @@ reduce_print (void) nuseless_productions), nuseless_productions); - fprintf (stderr, _("%s contains "), infile); + fprintf (stderr, "%s: %s: ", infile, _("warning")); if (nuseless_nonterminals > 0) fprintf (stderr, ngettext ("%d useless nonterminal", @@ -437,7 +447,7 @@ reduce_grammar (void) if (!bitset_test (N, axiom->number - ntokens)) fatal (_("Start symbol %s does not derive any sentence"), - quotearg_style (escape_quoting_style, symbols[axiom->number]->tag)); + symbol_tag_get (symbols[axiom->number])); /* First reduce the nonterminals, as they renumber themselves in the whole grammar. If you change the order, nonterms would be diff --git a/src/symtab.c b/src/symtab.c index fddf15e7..0f73d30f 100644 --- a/src/symtab.c +++ b/src/symtab.c @@ -20,6 +20,7 @@ #include "system.h" +#include "quotearg.h" #include "hash.h" #include "complain.h" #include "symtab.h" @@ -60,6 +61,41 @@ symbol_new (const char *tag, location_t location) } +/*-----------------------------------------------------------------. +| Return the tag of this SYMBOL in a printable form. Warning: use | +| the first QUOTEARG slot: 0. | +`-----------------------------------------------------------------*/ + +const char * +symbol_tag_get (symbol_t *symbol) +{ + return quotearg_style (escape_quoting_style, symbol->tag); +} + + +/*------------------------------------------------------------. +| Return the tag of this SYMBOL in a printable form. Use the | +| QUOTEARG slot number N. | +`------------------------------------------------------------*/ + +const char * +symbol_tag_get_n (symbol_t *symbol, int n) +{ + return quotearg_n_style (n, escape_quoting_style, symbol->tag); +} + + +/*-------------------------------. +| Print the tag of this SYMBOL. | +`-------------------------------*/ + +void +symbol_tag_print (symbol_t *symbol, FILE *out) +{ + fputs (symbol_tag_get (symbol), out); +} + + /*------------------------------------------------------------------. | Set the TYPE_NAME associated to SYMBOL. Does nothing if passed 0 | | as TYPE_NAME. | diff --git a/src/symtab.h b/src/symtab.h index 2f53c8b8..1424a41b 100644 --- a/src/symtab.h +++ b/src/symtab.h @@ -87,6 +87,17 @@ struct symbol_s #define NUMBER_UNDEFINED ((symbol_number_t) -1) +/* Return the tag of this SYMBOL in a printable form. Warning: uses + the QUOTEARG slot 0. */ +const char *symbol_tag_get PARAMS ((symbol_t *symbol)); + +/* Return the tag of this SYMBOL in a printable form. Use the + QUOTEARG slot number N. */ +const char *symbol_tag_get_n PARAMS ((symbol_t *symbol, int n)); + +/* Print the tag of this SYMBOL. */ +void symbol_tag_print PARAMS ((symbol_t *symbol, FILE *out)); + /* Fetch (or create) the symbol associated to KEY. */ symbol_t *getsym PARAMS ((const char *key, location_t location)); diff --git a/tests/conflicts.at b/tests/conflicts.at index 6d546783..3aceda1c 100644 --- a/tests/conflicts.at +++ b/tests/conflicts.at @@ -130,6 +130,8 @@ AT_CLEANUP AT_SETUP([Unresolved SR Conflicts]) +AT_KEYWORDS([report]) + AT_DATA([input.y], [[%token NUM OP %% @@ -147,10 +149,10 @@ AT_CHECK([cat input.output], [], Grammar - Number, Line, Rule - 0 3 $axiom -> exp $ - 1 3 exp -> exp OP exp - 2 3 exp -> NUM + 0 $axiom: exp $ + + 1 exp: exp OP exp + 2 | NUM Terminals, with rules where they appear @@ -241,6 +243,8 @@ AT_CLEANUP AT_SETUP([Solved SR Conflicts]) +AT_KEYWORDS([report]) + AT_DATA([input.y], [[%token NUM OP %right OP @@ -254,10 +258,10 @@ AT_CHECK([bison input.y -o input.c --report=all], 0, [], []) AT_CHECK([cat input.output], [], [[Grammar - Number, Line, Rule - 0 4 $axiom -> exp $ - 1 4 exp -> exp OP exp - 2 4 exp -> NUM + 0 $axiom: exp $ + + 1 exp: exp OP exp + 2 | NUM Terminals, with rules where they appear diff --git a/tests/reduce.at b/tests/reduce.at index 24911943..ba9d27ed 100644 --- a/tests/reduce.at +++ b/tests/reduce.at @@ -89,7 +89,16 @@ exp: useful; ]]) AT_CHECK([[bison input.y]], 0, [], -[[input.y contains 9 useless nonterminals +[[input.y: warning: 9 useless nonterminals +input.y:4.8-15: warning: useless nonterminal: useless1 +input.y:5.8-15: warning: useless nonterminal: useless2 +input.y:6.8-15: warning: useless nonterminal: useless3 +input.y:7.8-15: warning: useless nonterminal: useless4 +input.y:8.8-15: warning: useless nonterminal: useless5 +input.y:9.8-15: warning: useless nonterminal: useless6 +input.y:10.8-15: warning: useless nonterminal: useless7 +input.y:11.8-15: warning: useless nonterminal: useless8 +input.y:12.8-15: warning: useless nonterminal: useless9 ]]) AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0, @@ -133,7 +142,25 @@ useless9: '9'; ]]) AT_CHECK([[bison input.y]], 0, [], -[[input.y contains 9 useless nonterminals and 9 useless rules +[[input.y: warning: 9 useless nonterminals and 9 useless rules +input.y:6.1-8: warning: useless nonterminal: useless1 +input.y:7.1-8: warning: useless nonterminal: useless2 +input.y:8.1-8: warning: useless nonterminal: useless3 +input.y:9.1-8: warning: useless nonterminal: useless4 +input.y:10.1-8: warning: useless nonterminal: useless5 +input.y:11.1-8: warning: useless nonterminal: useless6 +input.y:12.1-8: warning: useless nonterminal: useless7 +input.y:13.1-8: warning: useless nonterminal: useless8 +input.y:14.1-8: warning: useless nonterminal: useless9 +input.y:6.9-13: warning: useless rule: useless1: '1' +input.y:7.9-13: warning: useless rule: useless2: '2' +input.y:8.9-13: warning: useless rule: useless3: '3' +input.y:9.9-13: warning: useless rule: useless4: '4' +input.y:10.9-13: warning: useless rule: useless5: '5' +input.y:11.9-13: warning: useless rule: useless6: '6' +input.y:12.9-13: warning: useless rule: useless7: '7' +input.y:13.9-13: warning: useless rule: useless8: '8' +input.y:14.9-13: warning: useless rule: useless9: '9' ]]) AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0, @@ -208,7 +235,12 @@ non_productive: non_productive useless_token ]]) AT_CHECK([[bison not-reduced.y]], 0, [], -[[not-reduced.y contains 2 useless nonterminals and 3 useless rules +[[not-reduced.y: warning: 2 useless nonterminals and 3 useless rules +not-reduced.y:14.1-13: warning: useless nonterminal: not_reachable +not-reduced.y:11.6-19: warning: useless nonterminal: non_productive +not-reduced.y:11.4-57: warning: useless rule: exp: non_productive +not-reduced.y:14.14-56: warning: useless rule: not_reachable: useful +not-reduced.y:17.15-18.63: warning: useless rule: non_productive: non_productive useless_token ]]) AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' not-reduced.output]], 0, @@ -275,7 +307,12 @@ indirection: underivable; ]]) AT_CHECK([[bison input.y]], 0, [], -[[input.y contains 2 useless nonterminals and 3 useless rules +[[input.y: warning: 2 useless nonterminals and 3 useless rules +input.y:5.15-25: warning: useless nonterminal: underivable +input.y:6.14-24: warning: useless nonterminal: indirection +input.y:5.13-25: warning: useless rule: exp: underivable +input.y:6.12-24: warning: useless rule: underivable: indirection +input.y:7.12-24: warning: useless rule: indirection: underivable ]]) AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0, diff --git a/tests/regression.at b/tests/regression.at index 6d559468..3620200a 100644 --- a/tests/regression.at +++ b/tests/regression.at @@ -112,6 +112,8 @@ AT_CLEANUP AT_SETUP([Rule Line Numbers]) +AT_KEYWORDS([report]) + AT_DATA([input.y], [[%% expr: @@ -148,12 +150,15 @@ AT_CHECK([bison input.y -o input.c -v]) AT_CHECK([cat input.output], [], [[Grammar - Number, Line, Rule - 0 5 $axiom -> expr $ - 1 5 @1 -> /* empty */ - 2 2 expr -> 'a' @1 'b' - 3 18 @2 -> /* empty */ - 4 15 expr -> @2 'c' + 0 $axiom: expr $ + + 1 @1: /* empty */ + + 2 expr: 'a' @1 'b' + + 3 @2: /* empty */ + + 4 expr: @2 'c' Terminals, with rules where they appear @@ -349,6 +354,8 @@ AT_CLEANUP AT_SETUP([Web2c Report]) +AT_KEYWORDS([report]) + AT_DATA([input.y], [[%token undef_id_tok const_id_tok @@ -375,13 +382,12 @@ AT_CHECK([bison -v input.y]) AT_CHECK([sed -n 's/ *$//;/^$/!p' input.output], 0, [[Grammar - Number, Line, Rule - 0 6 $axiom -> CONST_DEC_PART $ - 1 6 CONST_DEC_PART -> CONST_DEC_LIST - 2 10 CONST_DEC_LIST -> CONST_DEC - 3 12 CONST_DEC_LIST -> CONST_DEC_LIST CONST_DEC - 4 16 @1 -> /* empty */ - 5 15 CONST_DEC -> @1 undef_id_tok '=' const_id_tok ';' + 0 $axiom: CONST_DEC_PART $ + 1 CONST_DEC_PART: CONST_DEC_LIST + 2 CONST_DEC_LIST: CONST_DEC + 3 | CONST_DEC_LIST CONST_DEC + 4 @1: /* empty */ + 5 CONST_DEC: @1 undef_id_tok '=' const_id_tok ';' Terminals, with rules where they appear $ (0) 0 ';' (59) 5 @@ -470,6 +476,8 @@ AT_CLEANUP AT_SETUP([Web2c Actions]) +AT_KEYWORDS([report]) + AT_DATA([input.y], [[%% statement: struct_stat;