]> git.saurik.com Git - bison.git/commitdiff
Copy BYacc's nice way to report the grammar.
authorAkim Demaille <akim@epita.fr>
Sat, 15 Jun 2002 18:23:12 +0000 (18:23 +0000)
committerAkim Demaille <akim@epita.fr>
Sat, 15 Jun 2002 18:23:12 +0000 (18:23 +0000)
* 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.

16 files changed:
ChangeLog
NEWS
src/LR0.c
src/closure.c
src/gram.c
src/gram.h
src/lalr.c
src/output.c
src/print.c
src/print_graph.c
src/reduce.c
src/symtab.c
src/symtab.h
tests/conflicts.at
tests/reduce.at
tests/regression.at

index 27a927b0a6d253e37dcb41dcb7aa6dc52f4c20a6..4995682a312f347e23ad1daa4120b966a1e83a49 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,34 @@
+2002-06-15  Akim Demaille  <akim@epita.fr>
+
+       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  <akim@epita.fr>
+
+       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  <akim@epita.fr>
 
        Let symbols have a location.
diff --git a/NEWS b/NEWS
index 64258f23752c46f941e11eedb1b4aa9434630390..0dc405427086f70fc03682821e6d498b71747fe0 100644 (file)
--- 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
 
index efe9589ac946e7f657bf6ba39abec5da42566642..95200d53d8b27f1f5869cece72912e4bbd42f17c 100644 (file)
--- 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
index 928b686747127ab507e902a0cc754fdedbcd3d99..ea64250ea5aa9cf1741b26bc6a81c058f5974fac 100644 (file)
@@ -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);
          }
     }
index 90a0b527cb29c1e435d40d27419a497c6231228e..a1a0630853becd869f8466bfefead9b215eb454b 100644 (file)
@@ -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");
 }
index ff43ab8f4063c7d02c5d2e0e1933c9001c6219b2..962b9adbf1c2ad2e9e76e9625510563bef1f5282 100644 (file)
@@ -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));
 
index f3f37a7312028182167271cda6e5d072179d6d3a..dfc06bc9105343a7017facb8437fcb59003b7b23 100644 (file)
@@ -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");
index 832f4ed9037319e98ccab02cc09b99ef951151f6..7ee3214cab0b577e284062e0db82b7ae466529f1 100644 (file)
@@ -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;
index bcf71cc6deff48a7404f246e5b76c4370e503c45..280ac8d8417acbe5c4ffe8def58090df8968d31c 100644 (file)
@@ -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);
-}
-
 \f
 /*--------------------------------.
 | 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;
                  }
            }
index 6cd92ec9f58ab5792c93a2a8b89d6a184a354f7a..49acaa7ea460eca75f82c3206c4193c86d9c2d08 100644 (file)
 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);
       }
index 59afff78c01d33c321daef079b19d45c08e9ea27..2319b60bf192104f672ff22b0617b62015217824 100644 (file)
@@ -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
index fddf15e7af0d070419d576f602a626a5a1a7c31e..0f73d30f368398af475d4f6ca71055177c45d0b4 100644 (file)
@@ -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.                                                     |
index 2f53c8b8a12d70a0f48e3bb3b527421baacaa94e..1424a41b7cdd723467eb92f2d309c6d665c02572 100644 (file)
@@ -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));
 
index 6d5467838d9a3d656fe44aff28e2e9c8ae4b8b74..3aceda1cc72b5e2b62cad5516a6e30d6a17330da 100644 (file)
@@ -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
index 24911943aaa6c5f882e2ae8bccff195283cd92b5..ba9d27edd8e9cbcf0e49ffbf7039a96ac5a05c57 100644 (file)
@@ -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,
index 6d5594684b148258b6f7313b883149c4502c158a..3620200af6415cca7f136e87f71524ca74082fbb 100644 (file)
@@ -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;