]> git.saurik.com Git - bison.git/blobdiff - src/print.c
* src/lalr.h, src/lalr.c (tokensetsize): Remove, unused.
[bison.git] / src / print.c
index e80b5239e9c28e95c0a52d1b48e04dca6da888ba..17823f8ea401c721bcff8cc90148df32cdab65b0 100644 (file)
@@ -1,5 +1,5 @@
 /* Print information on generated parser, for bison,
 /* Print information on generated parser, for bison,
-   Copyright 1984, 1986, 1989, 2000, 2001 Free Software Foundation, Inc.
+   Copyright 1984, 1986, 1989, 2000, 2001, 2002 Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
 
    This file is part of Bison, the GNU Compiler Compiler.
 
@@ -20,7 +20,9 @@
 
 
 #include "system.h"
 
 
 #include "system.h"
+#include "quotearg.h"
 #include "files.h"
 #include "files.h"
+#include "symtab.h"
 #include "gram.h"
 #include "LR0.h"
 #include "lalr.h"
 #include "gram.h"
 #include "LR0.h"
 #include "lalr.h"
 #include "print.h"
 #include "reduce.h"
 #include "closure.h"
 #include "print.h"
 #include "reduce.h"
 #include "closure.h"
+#include "bitset.h"
+
+static bitset shiftset;
+static bitset lookaheadset;
 
 #if 0
 static void
 
 #if 0
 static void
@@ -40,17 +46,30 @@ print_token (int extnum, int token)
 }
 #endif
 
 }
 #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.  |
 `--------------------------------*/
 
 static void
 \f
 /*--------------------------------.
 | Report information on a state.  |
 `--------------------------------*/
 
 static void
-print_core (FILE *out, int state)
+print_core (FILE *out, state_t *state)
 {
   int i;
 {
   int i;
-  short *sitems = state_table[state]->items;
-  int snitems   = state_table[state]->nitems;
+  short *sitems = state->items;
+  int snitems   = state->nitems;
 
   /* New experimental feature: if TRACE_FLAGS output all the items of
      a state, not only its kernel.  */
 
   /* New experimental feature: if TRACE_FLAGS output all the items of
      a state, not only its kernel.  */
@@ -71,21 +90,21 @@ print_core (FILE *out, int state)
 
          sp1 = sp = ritem + sitems[i];
 
 
          sp1 = sp = ritem + sitems[i];
 
-         while (*sp > 0)
+         while (*sp >= 0)
            sp++;
 
          rule = -(*sp);
            sp++;
 
          rule = -(*sp);
-         fprintf (out, "    %s  ->  ", tags[rule_table[rule].lhs]);
+         fprintf (out, "    %s  ->  ", escape (symbols[rules[rule].lhs]->tag));
 
 
-         for (sp = ritem + rule_table[rule].rhs; sp < sp1; sp++)
-           fprintf (out, "%s ", tags[*sp]);
+         for (sp = ritem + rules[rule].rhs; sp < sp1; sp++)
+           fprintf (out, "%s ", escape (symbols[*sp]->tag));
 
          fputc ('.', out);
 
 
          fputc ('.', out);
 
-         for (/* Nothing */; *sp > 0; ++sp)
-           fprintf (out, " %s", tags[*sp]);
+         for (/* Nothing */; *sp >= 0; ++sp)
+           fprintf (out, " %s", escape (symbols[*sp]->tag));
 
 
-         fprintf (out, _("   (rule %d)"), rule);
+         fprintf (out, _("   (rule %d)"), rule - 1);
          fputc ('\n', out);
        }
 
          fputc ('\n', out);
        }
 
@@ -93,91 +112,239 @@ print_core (FILE *out, int state)
     }
 }
 
     }
 }
 
+
 static void
 static void
-print_actions (FILE *out, int state)
+print_shifts (FILE *out, state_t *state)
 {
   int i;
 {
   int i;
+  shifts *shiftp = state->shifts;
 
 
-  shifts   *shiftp = state_table[state]->shifts;
-  reductions *redp = state_table[state]->reductions;
-  errs       *errp = state_table[state]->errs;
-
-  if (!shiftp->nshifts && !redp)
-    {
-      if (final_state == state)
-       fprintf (out, _("    $default\taccept\n"));
-      else
-       fprintf (out, _("    NO ACTIONS\n"));
-      return;
-    }
-
-  for (i = 0; i < shiftp->nshifts; i++)
+  for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
     if (!SHIFT_IS_DISABLED (shiftp, i))
       {
        int state1 = shiftp->shifts[i];
     if (!SHIFT_IS_DISABLED (shiftp, i))
       {
        int state1 = shiftp->shifts[i];
-       int symbol = state_table[state1]->accessing_symbol;
-       /* The following line used to be turned off.  */
-       if (ISVAR (symbol))
-         break;
-       if (symbol == 0)        /* I.e. strcmp(tags[symbol],"$")==0 */
-         fprintf (out,
-                  _("    $   \tgo to state %d\n"), state1);
-       else
-         fprintf (out,
-                  _("    %-4s\tshift, and go to state %d\n"),
-                  tags[symbol], state1);
+       int symbol = states[state1]->accessing_symbol;
+       fprintf (out,
+                _("    %-4s\tshift, and go to state %d\n"),
+                escape (symbols[symbol]->tag), state1);
       }
 
   if (i > 0)
     fputc ('\n', out);
       }
 
   if (i > 0)
     fputc ('\n', out);
+}
+
+
+static void
+print_errs (FILE *out, state_t *state)
+{
+  errs *errp = state->errs;
+  int i;
+
+  for (i = 0; i < errp->nerrs; ++i)
+    if (errp->errs[i])
+      fprintf (out, _("    %-4s\terror (nonassociative)\n"),
+              escape (symbols[errp->errs[i]]->tag));
+
+  if (i > 0)
+    fputc ('\n', out);
+}
 
 
-  if (errp)
+
+static void
+print_gotos (FILE *out, state_t *state)
+{
+  int i;
+  shifts *shiftp = state->shifts;
+
+  for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
+    /* Skip token shifts.  */;
+
+  if (i < shiftp->nshifts)
     {
     {
-      int j;
-      for (j = 0; j < errp->nerrs; j++)
-       {
-         int symbol = errp->errs[j];
-         if (!symbol)
-           continue;
-         fprintf (out, _("    %-4s\terror (nonassociative)\n"),
-                  tags[symbol]);
-       }
+      for (; i < shiftp->nshifts; i++)
+       if (!SHIFT_IS_DISABLED (shiftp, i))
+         {
+           int state1 = shiftp->shifts[i];
+           int symbol = states[state1]->accessing_symbol;
+           fprintf (out, _("    %-4s\tgo to state %d\n"),
+                    escape (symbols[symbol]->tag), state1);
+         }
 
 
-      if (j > 0)
-       fputc ('\n', out);
+      fputc ('\n', out);
     }
     }
+}
 
 
-  if (state_table[state]->consistent && redp)
+static void
+print_reductions (FILE *out, state_t *state)
+{
+  int i;
+  shifts *shiftp = state->shifts;
+  reductions *redp = state->reductions;
+  errs *errp = state->errs;
+  int nodefault = 0;
+
+  if (redp->nreds == 0)
+    return;
+
+  if (state->consistent)
     {
       int rule = redp->rules[0];
     {
       int rule = redp->rules[0];
-      int symbol = rule_table[rule].lhs;
+      int symbol = rules[rule].lhs;
       fprintf (out, _("    $default\treduce using rule %d (%s)\n\n"),
       fprintf (out, _("    $default\treduce using rule %d (%s)\n\n"),
-              rule, tags[symbol]);
+              rule - 1, escape (symbols[symbol]->tag));
+      return;
     }
     }
-  else if (redp)
+
+  bitset_zero (shiftset);
+
+  for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
+    if (!SHIFT_IS_DISABLED (shiftp, i))
+      {
+       /* if this state has a shift for the error token, don't use a
+          default rule.  */
+       if (SHIFT_IS_ERROR (shiftp, i))
+         nodefault = 1;
+       bitset_set (shiftset, SHIFT_SYMBOL (shiftp, i));
+      }
+
+  for (i = 0; i < errp->nerrs; i++)
+    if (errp->errs[i])
+      bitset_set (shiftset, errp->errs[i]);
+
+  if (state->nlookaheads == 1 && !nodefault)
     {
     {
-      print_reductions (out, state);
-    }
+      int default_rule = LAruleno[state->lookaheadsp];
 
 
-  if (i < shiftp->nshifts)
+      for (i = 0; i < ntokens; ++i)
+       if (bitset_test (LA[state->lookaheadsp], i)
+           && bitset_test (shiftset, i))
+         bitset_set (lookaheadset, i);
+       else
+         bitset_reset (lookaheadset, i);
+
+      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), default_rule - 1,
+                  escape2 (symbols[rules[default_rule].lhs]->tag));
+
+      fprintf (out, _("    $default\treduce using rule %d (%s)\n\n"),
+              default_rule - 1, escape (symbols[rules[default_rule].lhs]->tag));
+    }
+  else if (state->nlookaheads >= 1)
     {
     {
-      for (; i < shiftp->nshifts; i++)
-       if (!SHIFT_IS_DISABLED (shiftp, i))
+      int cmax = 0;
+      int default_LA = -1;
+      int default_rule = 0;
+
+      if (!nodefault)
+       for (i = 0; i < state->nlookaheads; ++i)
          {
          {
-           int state1 = shiftp->shifts[i];
-           int symbol = state_table[state1]->accessing_symbol;
-           fprintf (out, _("    %-4s\tgo to state %d\n"),
-                    tags[symbol], state1);
+           int count = 0;
+           int j, k;
+
+           for (k = 0; k < ntokens; ++k)
+             if (bitset_test (LA[state->lookaheadsp + i], k)
+                 && ! bitset_test (shiftset, k))
+               bitset_set (lookaheadset, k);
+             else
+               bitset_reset (lookaheadset, k);
+
+           for (j = 0; j < ntokens; j++)
+             if (bitset_test (lookaheadset, j))
+               count++;
+
+           if (count > cmax)
+             {
+               cmax = count;
+               default_LA = state->lookaheadsp + i;
+               default_rule = LAruleno[state->lookaheadsp + i];
+             }
+
+           bitset_or (shiftset, shiftset, lookaheadset);
          }
 
          }
 
-      fputc ('\n', out);
+      bitset_zero (shiftset);
+
+      for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
+       if (!SHIFT_IS_DISABLED (shiftp, i))
+         bitset_set (shiftset, SHIFT_SYMBOL (shiftp, i));
+
+      for (i = 0; i < ntokens; i++)
+       {
+         int j;
+         int defaulted = 0;
+         int count = bitset_test (shiftset, i);
+
+         for (j = 0; j < state->nlookaheads; ++j)
+           {
+             if (bitset_test (LA[state->lookaheadsp + j], i))
+               {
+                 if (count == 0)
+                   {
+                     if (state->lookaheadsp + j != default_LA)
+                       fprintf (out,
+                                _("    %-4s\treduce using rule %d (%s)\n"),
+                                escape (symbols[i]->tag),
+                                LAruleno[state->lookaheadsp + j] - 1,
+                                escape2 (symbols[rules[LAruleno[state->lookaheadsp + j]].lhs]->tag));
+                     else
+                       defaulted = 1;
+
+                     count++;
+                   }
+                 else
+                   {
+                     if (defaulted)
+                       fprintf (out,
+                                _("    %-4s\treduce using rule %d (%s)\n"),
+                                escape (symbols[i]->tag),
+                                LAruleno[default_LA] - 1,
+                                escape2 (symbols[rules[LAruleno[default_LA]].lhs]->tag));
+                     defaulted = 0;
+                     fprintf (out,
+                              _("    %-4s\t[reduce using rule %d (%s)]\n"),
+                              escape (symbols[i]->tag),
+                              LAruleno[state->lookaheadsp + j] - 1,
+                              escape2 (symbols[rules[LAruleno[state->lookaheadsp + j]].lhs]->tag));
+                   }
+               }
+           }
+       }
+
+      if (default_LA >= 0)
+       fprintf (out, _("    $default\treduce using rule %d (%s)\n"),
+                default_rule - 1,
+                escape (symbols[rules[default_rule].lhs]->tag));
+    }
+}
+
+
+static void
+print_actions (FILE *out, state_t *state)
+{
+  reductions *redp = state->reductions;
+  shifts *shiftp = state->shifts;
+
+  if (shiftp->nshifts == 0 && redp->nreds == 0)
+    {
+      if (final_state == state->number)
+       fprintf (out, _("    $default\taccept\n"));
+      else
+       fprintf (out, _("    NO ACTIONS\n"));
+      return;
     }
     }
+
+  print_shifts (out, state);
+  print_errs (out, state);
+  print_reductions (out, state);
+  print_gotos (out, state);
 }
 
 static void
 }
 
 static void
-print_state (FILE *out, int state)
+print_state (FILE *out, state_t *state)
 {
 {
-  fprintf (out, _("state %d"), state);
+  fprintf (out, _("state %d"), state->number);
   fputs ("\n\n", out);
   print_core (out, state);
   print_actions (out, state);
   fputs ("\n\n", out);
   print_core (out, state);
   print_actions (out, state);
@@ -212,14 +379,14 @@ print_grammar (FILE *out)
   fprintf (out, "  %s\n", _("Number, Line, Rule"));
   for (i = 1; i <= nrules; i++)
     /* Don't print rules disabled in reduce_grammar_tables.  */
   fprintf (out, "  %s\n", _("Number, Line, Rule"));
   for (i = 1; i <= nrules; i++)
     /* Don't print rules disabled in reduce_grammar_tables.  */
-    if (rule_table[i].useful)
+    if (rules[i].useful)
       {
        fprintf (out, _("  %3d %3d %s ->"),
       {
        fprintf (out, _("  %3d %3d %s ->"),
-                i, rule_table[i].line, tags[rule_table[i].lhs]);
-       rule = &ritem[rule_table[i].rhs];
-       if (*rule > 0)
-         while (*rule > 0)
-           fprintf (out, " %s", tags[*rule++]);
+                i - 1, rules[i].line, escape (symbols[rules[i].lhs]->tag));
+       rule = &ritem[rules[i].rhs];
+       if (*rule >= 0)
+         while (*rule >= 0)
+           fprintf (out, " %s", escape (symbols[*rule++]->tag));
        else
          fprintf (out, " /* %s */", _("empty"));
        fputc ('\n', out);
        else
          fprintf (out, " /* %s */", _("empty"));
        fputc ('\n', out);
@@ -229,23 +396,21 @@ print_grammar (FILE *out)
 
   /* TERMINAL (type #) : rule #s terminal is on RHS */
   fprintf (out, "%s\n\n", _("Terminals, with rules where they appear"));
 
   /* TERMINAL (type #) : rule #s terminal is on RHS */
   fprintf (out, "%s\n\n", _("Terminals, with rules where they appear"));
-  fprintf (out, "%s (-1)\n", tags[0]);
-
   for (i = 0; i <= max_user_token_number; i++)
     if (token_translations[i] != 2)
       {
        buffer[0] = 0;
   for (i = 0; i <= max_user_token_number; i++)
     if (token_translations[i] != 2)
       {
        buffer[0] = 0;
-       column = strlen (tags[token_translations[i]]);
-       fputs (tags[token_translations[i]], out);
+       column = strlen (escape (symbols[token_translations[i]]->tag));
+       fputs (escape (symbols[token_translations[i]]->tag), out);
        END_TEST (50);
        sprintf (buffer, " (%d)", i);
 
        for (j = 1; j <= nrules; j++)
        END_TEST (50);
        sprintf (buffer, " (%d)", i);
 
        for (j = 1; j <= nrules; j++)
-         for (rule = &ritem[rule_table[j].rhs]; *rule > 0; rule++)
+         for (rule = &ritem[rules[j].rhs]; *rule >= 0; rule++)
            if (*rule == token_translations[i])
              {
                END_TEST (65);
            if (*rule == token_translations[i])
              {
                END_TEST (65);
-               sprintf (buffer + strlen (buffer), " %d", j);
+               sprintf (buffer + strlen (buffer), " %d", j - 1);
                break;
              }
        fprintf (out, "%s\n", buffer);
                break;
              }
        fprintf (out, "%s\n", buffer);
@@ -260,9 +425,9 @@ print_grammar (FILE *out)
 
       for (j = 1; j <= nrules; j++)
        {
 
       for (j = 1; j <= nrules; j++)
        {
-         if (rule_table[j].lhs == i)
+         if (rules[j].lhs == i)
            left_count++;
            left_count++;
-         for (rule = &ritem[rule_table[j].rhs]; *rule > 0; rule++)
+         for (rule = &ritem[rules[j].rhs]; *rule >= 0; rule++)
            if (*rule == i)
              {
                right_count++;
            if (*rule == i)
              {
                right_count++;
@@ -271,8 +436,8 @@ print_grammar (FILE *out)
        }
 
       buffer[0] = 0;
        }
 
       buffer[0] = 0;
-      fputs (tags[i], out);
-      column = strlen (tags[i]);
+      fputs (escape (symbols[i]->tag), out);
+      column = strlen (escape (symbols[i]->tag));
       sprintf (buffer, " (%d)", i);
       END_TEST (0);
 
       sprintf (buffer, " (%d)", i);
       END_TEST (0);
 
@@ -284,8 +449,8 @@ print_grammar (FILE *out)
          for (j = 1; j <= nrules; j++)
            {
              END_TEST (65);
          for (j = 1; j <= nrules; j++)
            {
              END_TEST (65);
-             if (rule_table[j].lhs == i)
-               sprintf (buffer + strlen (buffer), " %d", j);
+             if (rules[j].lhs == i)
+               sprintf (buffer + strlen (buffer), " %d", j - 1);
            }
        }
 
            }
        }
 
@@ -297,11 +462,11 @@ print_grammar (FILE *out)
          sprintf (buffer + strlen (buffer), _(" on right:"));
          for (j = 1; j <= nrules; j++)
            {
          sprintf (buffer + strlen (buffer), _(" on right:"));
          for (j = 1; j <= nrules; j++)
            {
-             for (rule = &ritem[rule_table[j].rhs]; *rule > 0; rule++)
+             for (rule = &ritem[rules[j].rhs]; *rule >= 0; rule++)
                if (*rule == i)
                  {
                    END_TEST (65);
                if (*rule == i)
                  {
                    END_TEST (65);
-                   sprintf (buffer + strlen (buffer), " %d", j);
+                   sprintf (buffer + strlen (buffer), " %d", j - 1);
                    break;
                  }
            }
                    break;
                  }
            }
@@ -314,35 +479,40 @@ print_grammar (FILE *out)
 void
 print_results (void)
 {
 void
 print_results (void)
 {
-  if (verbose_flag)
-    {
-      int i;
+  size_t i;
 
 
-      /* We used to use just .out if spec_name_prefix (-p) was used, but
-        that conflicts with Posix.  */
-      FILE *out = xfopen (spec_verbose_file, "w");
+  /* We used to use just .out if SPEC_NAME_PREFIX (-p) was used, but
+     that conflicts with Posix.  */
+  FILE *out = xfopen (spec_verbose_file, "w");
 
 
-      size_t size = obstack_object_size (&output_obstack);
-      fwrite (obstack_finish (&output_obstack), 1, size, out);
-      if (size)
-       fputs ("\n\n", out);
+  size_t size = obstack_object_size (&output_obstack);
+  fwrite (obstack_finish (&output_obstack), 1, size, out);
+  obstack_free (&output_obstack, NULL);
 
 
-      reduce_output (out);
-      conflicts_output (out);
+  if (size)
+    fputs ("\n\n", out);
 
 
-      print_grammar (out);
+  reduce_output (out);
+  conflicts_output (out);
 
 
-      /* New experimental feature: output all the items of a state,
-        not only its kernel.  Requires to run closure, which need
-        memory allocation/deallocation.  */
-      if (trace_flag)
-       new_closure (nitems);
-      for (i = 0; i < nstates; i++)
-       print_state (out, i);
-      if (trace_flag)
-       free_closure ();
+  print_grammar (out);
 
 
-      xfclose (out);
-    }
-  obstack_free (&output_obstack, NULL);
+  /* New experimental feature: output all the items of a state, not
+     only its kernel.  Requires to run closure, which need memory
+     allocation/deallocation.  */
+  if (trace_flag)
+    new_closure (nritems);
+  /* Storage for print_reductions.  */
+  shiftset =  bitset_create (ntokens, BITSET_FIXED);
+  bitset_zero (shiftset);
+  lookaheadset = bitset_create (ntokens, BITSET_FIXED);
+  bitset_zero (lookaheadset);
+  for (i = 0; i < nstates; i++)
+    print_state (out, states[i]);
+  bitset_free (shiftset);
+  bitset_free (lookaheadset);
+  if (trace_flag)
+    free_closure ();
+
+  xfclose (out);
 }
 }