Home | History | Annotate | Download | only in src
      1 /* Print information on generated parser, for bison,
      2 
      3    Copyright (C) 1984, 1986, 1989, 2000-2005, 2007, 2009-2012 Free
      4    Software Foundation, Inc.
      5 
      6    This file is part of Bison, the GNU Compiler Compiler.
      7 
      8    This program is free software: you can redistribute it and/or modify
      9    it under the terms of the GNU General Public License as published by
     10    the Free Software Foundation, either version 3 of the License, or
     11    (at your option) any later version.
     12 
     13    This program is distributed in the hope that it will be useful,
     14    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16    GNU General Public License for more details.
     17 
     18    You should have received a copy of the GNU General Public License
     19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     20 
     21 #include <config.h>
     22 #include "system.h"
     23 
     24 #include <bitset.h>
     25 
     26 #include "LR0.h"
     27 #include "closure.h"
     28 #include "conflicts.h"
     29 #include "files.h"
     30 #include "getargs.h"
     31 #include "gram.h"
     32 #include "lalr.h"
     33 #include "muscle-tab.h"
     34 #include "print.h"
     35 #include "reader.h"
     36 #include "reduce.h"
     37 #include "state.h"
     38 #include "symtab.h"
     39 #include "tables.h"
     40 
     41 static bitset no_reduce_set;
     42 
     43 #if 0
     44 static void
     45 print_token (int extnum, int token)
     46 {
     47   fprintf (out, _(" type %d is %s\n"), extnum, tags[token]);
     48 }
     49 #endif
     50 
     51 
     52 
     54 /*---------------------------------------.
     55 | *WIDTH := max (*WIDTH, strlen (STR)).  |
     56 `---------------------------------------*/
     57 
     58 static void
     59 max_length (size_t *width, const char *str)
     60 {
     61   size_t len = strlen (str);
     62   if (len > *width)
     63     *width = len;
     64 }
     65 
     66 /*--------------------------------.
     67 | Report information on a state.  |
     68 `--------------------------------*/
     69 
     70 static void
     71 print_core (FILE *out, state *s)
     72 {
     73   size_t i;
     74   item_number *sitems = s->items;
     75   size_t snritems = s->nitems;
     76   symbol *previous_lhs = NULL;
     77 
     78   /* Output all the items of a state, not only its kernel.  */
     79   if (report_flag & report_itemsets)
     80     {
     81       closure (sitems, snritems);
     82       sitems = itemset;
     83       snritems = nitemset;
     84     }
     85 
     86   if (!snritems)
     87     return;
     88 
     89   fputc ('\n', out);
     90 
     91   for (i = 0; i < snritems; i++)
     92     {
     93       item_number *sp;
     94       item_number *sp1;
     95       rule_number r;
     96 
     97       sp1 = sp = ritem + sitems[i];
     98 
     99       while (*sp >= 0)
    100 	sp++;
    101 
    102       r = item_number_as_rule_number (*sp);
    103 
    104       rule_lhs_print (&rules[r], previous_lhs, out);
    105       previous_lhs = rules[r].lhs;
    106 
    107       for (sp = rules[r].rhs; sp < sp1; sp++)
    108 	fprintf (out, " %s", symbols[*sp]->tag);
    109       fputs (" .", out);
    110       for (/* Nothing */; *sp >= 0; ++sp)
    111 	fprintf (out, " %s", symbols[*sp]->tag);
    112 
    113       /* Display the lookahead tokens?  */
    114       if (report_flag & report_lookahead_tokens
    115           && item_number_is_rule_number (*sp1))
    116 	state_rule_lookahead_tokens_print (s, &rules[r], out);
    117 
    118       fputc ('\n', out);
    119     }
    120 }
    121 
    122 
    123 /*------------------------------------------------------------.
    124 | Report the shifts iff DISPLAY_SHIFTS_P or the gotos of S on |
    125 | OUT.                                                        |
    126 `------------------------------------------------------------*/
    127 
    128 static void
    129 print_transitions (state *s, FILE *out, bool display_transitions_p)
    130 {
    131   transitions *trans = s->transitions;
    132   size_t width = 0;
    133   int i;
    134 
    135   /* Compute the width of the lookahead token column.  */
    136   for (i = 0; i < trans->num; i++)
    137     if (!TRANSITION_IS_DISABLED (trans, i)
    138 	&& TRANSITION_IS_SHIFT (trans, i) == display_transitions_p)
    139       {
    140 	symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)];
    141 	max_length (&width, sym->tag);
    142       }
    143 
    144   /* Nothing to report. */
    145   if (!width)
    146     return;
    147 
    148   fputc ('\n', out);
    149   width += 2;
    150 
    151   /* Report lookahead tokens and shifts.  */
    152   for (i = 0; i < trans->num; i++)
    153     if (!TRANSITION_IS_DISABLED (trans, i)
    154 	&& TRANSITION_IS_SHIFT (trans, i) == display_transitions_p)
    155       {
    156 	symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)];
    157 	const char *tag = sym->tag;
    158 	state *s1 = trans->states[i];
    159 	int j;
    160 
    161 	fprintf (out, "    %s", tag);
    162 	for (j = width - strlen (tag); j > 0; --j)
    163 	  fputc (' ', out);
    164 	if (display_transitions_p)
    165 	  fprintf (out, _("shift, and go to state %d\n"), s1->number);
    166 	else
    167 	  fprintf (out, _("go to state %d\n"), s1->number);
    168       }
    169 }
    170 
    171 
    172 /*--------------------------------------------------------.
    173 | Report the explicit errors of S raised from %nonassoc.  |
    174 `--------------------------------------------------------*/
    175 
    176 static void
    177 print_errs (FILE *out, state *s)
    178 {
    179   errs *errp = s->errs;
    180   size_t width = 0;
    181   int i;
    182 
    183   /* Compute the width of the lookahead token column.  */
    184   for (i = 0; i < errp->num; ++i)
    185     if (errp->symbols[i])
    186       max_length (&width, errp->symbols[i]->tag);
    187 
    188   /* Nothing to report. */
    189   if (!width)
    190     return;
    191 
    192   fputc ('\n', out);
    193   width += 2;
    194 
    195   /* Report lookahead tokens and errors.  */
    196   for (i = 0; i < errp->num; ++i)
    197     if (errp->symbols[i])
    198       {
    199 	const char *tag = errp->symbols[i]->tag;
    200 	int j;
    201 	fprintf (out, "    %s", tag);
    202 	for (j = width - strlen (tag); j > 0; --j)
    203 	  fputc (' ', out);
    204 	fputs (_("error (nonassociative)\n"), out);
    205       }
    206 }
    207 
    208 
    209 /*-------------------------------------------------------------------------.
    210 | Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be `default').  |
    211 | If not ENABLED, the rule is masked by a shift or a reduce (S/R and       |
    212 | R/R conflicts).                                                          |
    213 `-------------------------------------------------------------------------*/
    214 
    215 static void
    216 print_reduction (FILE *out, size_t width,
    217 		 const char *lookahead_token,
    218 		 rule *r, bool enabled)
    219 {
    220   int j;
    221   fprintf (out, "    %s", lookahead_token);
    222   for (j = width - strlen (lookahead_token); j > 0; --j)
    223     fputc (' ', out);
    224   if (!enabled)
    225     fputc ('[', out);
    226   if (r->number)
    227     fprintf (out, _("reduce using rule %d (%s)"), r->number, r->lhs->tag);
    228   else
    229     fprintf (out, _("accept"));
    230   if (!enabled)
    231     fputc (']', out);
    232   fputc ('\n', out);
    233 }
    234 
    235 
    236 /*-------------------------------------------.
    237 | Report on OUT the reduction actions of S.  |
    238 `-------------------------------------------*/
    239 
    240 static void
    241 print_reductions (FILE *out, state *s)
    242 {
    243   transitions *trans = s->transitions;
    244   reductions *reds = s->reductions;
    245   rule *default_reduction = NULL;
    246   size_t width = 0;
    247   int i, j;
    248   bool default_reduction_only = true;
    249 
    250   if (reds->num == 0)
    251     return;
    252 
    253   if (yydefact[s->number] != 0)
    254     default_reduction = &rules[yydefact[s->number] - 1];
    255 
    256   bitset_zero (no_reduce_set);
    257   FOR_EACH_SHIFT (trans, i)
    258     bitset_set (no_reduce_set, TRANSITION_SYMBOL (trans, i));
    259   for (i = 0; i < s->errs->num; ++i)
    260     if (s->errs->symbols[i])
    261       bitset_set (no_reduce_set, s->errs->symbols[i]->number);
    262 
    263   /* Compute the width of the lookahead token column.  */
    264   if (default_reduction)
    265     width = strlen (_("$default"));
    266 
    267   if (reds->lookahead_tokens)
    268     for (i = 0; i < ntokens; i++)
    269       {
    270 	bool count = bitset_test (no_reduce_set, i);
    271 
    272 	for (j = 0; j < reds->num; ++j)
    273 	  if (bitset_test (reds->lookahead_tokens[j], i))
    274 	    {
    275 	      if (! count)
    276 		{
    277 		  if (reds->rules[j] != default_reduction)
    278 		    max_length (&width, symbols[i]->tag);
    279 		  count = true;
    280 		}
    281 	      else
    282 		{
    283 		  max_length (&width, symbols[i]->tag);
    284 		}
    285 	    }
    286       }
    287 
    288   /* Nothing to report. */
    289   if (!width)
    290     return;
    291 
    292   fputc ('\n', out);
    293   width += 2;
    294 
    295   /* Report lookahead tokens (or $default) and reductions.  */
    296   if (reds->lookahead_tokens)
    297     for (i = 0; i < ntokens; i++)
    298       {
    299 	bool defaulted = false;
    300 	bool count = bitset_test (no_reduce_set, i);
    301         if (count)
    302           default_reduction_only = false;
    303 
    304 	for (j = 0; j < reds->num; ++j)
    305 	  if (bitset_test (reds->lookahead_tokens[j], i))
    306 	    {
    307 	      if (! count)
    308 		{
    309 		  if (reds->rules[j] != default_reduction)
    310                     {
    311                       default_reduction_only = false;
    312                       print_reduction (out, width,
    313                                        symbols[i]->tag,
    314                                        reds->rules[j], true);
    315                     }
    316 		  else
    317 		    defaulted = true;
    318 		  count = true;
    319 		}
    320 	      else
    321 		{
    322                   default_reduction_only = false;
    323 		  if (defaulted)
    324 		    print_reduction (out, width,
    325 				     symbols[i]->tag,
    326 				     default_reduction, true);
    327 		  defaulted = false;
    328 		  print_reduction (out, width,
    329 				   symbols[i]->tag,
    330 				   reds->rules[j], false);
    331 		}
    332 	    }
    333       }
    334 
    335   if (default_reduction)
    336     {
    337       char *default_reductions =
    338         muscle_percent_define_get ("lr.default-reductions");
    339       print_reduction (out, width, _("$default"), default_reduction, true);
    340       aver (0 == strcmp (default_reductions, "most")
    341             || (0 == strcmp (default_reductions, "consistent")
    342                 && default_reduction_only)
    343             || (reds->num == 1 && reds->rules[0]->number == 0));
    344       free (default_reductions);
    345     }
    346 }
    347 
    348 
    349 /*--------------------------------------------------------------.
    350 | Report on OUT all the actions (shifts, gotos, reductions, and |
    351 | explicit erros from %nonassoc) of S.                          |
    352 `--------------------------------------------------------------*/
    353 
    354 static void
    355 print_actions (FILE *out, state *s)
    356 {
    357   /* Print shifts.  */
    358   print_transitions (s, out, true);
    359   print_errs (out, s);
    360   print_reductions (out, s);
    361   /* Print gotos.  */
    362   print_transitions (s, out, false);
    363 }
    364 
    365 
    366 /*----------------------------------.
    367 | Report all the data on S on OUT.  |
    368 `----------------------------------*/
    369 
    370 static void
    371 print_state (FILE *out, state *s)
    372 {
    373   fputs ("\n\n", out);
    374   fprintf (out, _("State %d"), s->number);
    375   fputc ('\n', out);
    376   print_core (out, s);
    377   print_actions (out, s);
    378   if ((report_flag & report_solved_conflicts) && s->solved_conflicts)
    379     {
    380       fputc ('\n', out);
    381       fputs (s->solved_conflicts, out);
    382     }
    383 }
    384 
    385 /*-----------------------------------------.
    387 | Print information on the whole grammar.  |
    388 `-----------------------------------------*/
    389 
    390 #define END_TEST(End)				\
    391 do {						\
    392   if (column + strlen(buffer) > (End))		\
    393     {						\
    394       fprintf (out, "%s\n   ", buffer);		\
    395       column = 3;				\
    396       buffer[0] = 0;				\
    397     }						\
    398 } while (0)
    399 
    400 
    401 static void
    402 print_grammar (FILE *out)
    403 {
    404   symbol_number i;
    405   char buffer[90];
    406   int column = 0;
    407 
    408   grammar_rules_print (out);
    409 
    410   /* TERMINAL (type #) : rule #s terminal is on RHS */
    411   fprintf (out, "%s\n\n", _("Terminals, with rules where they appear"));
    412   for (i = 0; i < max_user_token_number + 1; i++)
    413     if (token_translations[i] != undeftoken->number)
    414       {
    415 	const char *tag = symbols[token_translations[i]]->tag;
    416 	rule_number r;
    417 	item_number *rhsp;
    418 
    419 	buffer[0] = 0;
    420 	column = strlen (tag);
    421 	fputs (tag, out);
    422 	END_TEST (65);
    423 	sprintf (buffer, " (%d)", i);
    424 
    425 	for (r = 0; r < nrules; r++)
    426 	  for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++)
    427 	    if (item_number_as_symbol_number (*rhsp) == token_translations[i])
    428 	      {
    429 		END_TEST (65);
    430 		sprintf (buffer + strlen (buffer), " %d", r);
    431 		break;
    432 	      }
    433 	fprintf (out, "%s\n", buffer);
    434       }
    435   fputs ("\n\n", out);
    436 
    437 
    438   fprintf (out, "%s\n\n", _("Nonterminals, with rules where they appear"));
    439   for (i = ntokens; i < nsyms; i++)
    440     {
    441       int left_count = 0, right_count = 0;
    442       rule_number r;
    443       const char *tag = symbols[i]->tag;
    444 
    445       for (r = 0; r < nrules; r++)
    446 	{
    447 	  item_number *rhsp;
    448 	  if (rules[r].lhs->number == i)
    449 	    left_count++;
    450 	  for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++)
    451 	    if (item_number_as_symbol_number (*rhsp) == i)
    452 	      {
    453 		right_count++;
    454 		break;
    455 	      }
    456 	}
    457 
    458       buffer[0] = 0;
    459       fputs (tag, out);
    460       column = strlen (tag);
    461       sprintf (buffer, " (%d)", i);
    462       END_TEST (0);
    463 
    464       if (left_count > 0)
    465 	{
    466 	  END_TEST (65);
    467 	  sprintf (buffer + strlen (buffer), _(" on left:"));
    468 
    469 	  for (r = 0; r < nrules; r++)
    470 	    {
    471 	      if (rules[r].lhs->number == i)
    472 		{
    473 		  END_TEST (65);
    474 		  sprintf (buffer + strlen (buffer), " %d", r);
    475 		}
    476 	    }
    477 	}
    478 
    479       if (right_count > 0)
    480 	{
    481 	  if (left_count > 0)
    482 	    sprintf (buffer + strlen (buffer), ",");
    483 	  END_TEST (65);
    484 	  sprintf (buffer + strlen (buffer), _(" on right:"));
    485 	  for (r = 0; r < nrules; r++)
    486 	    {
    487 	      item_number *rhsp;
    488 	      for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++)
    489 		if (item_number_as_symbol_number (*rhsp) == i)
    490 		  {
    491 		    END_TEST (65);
    492 		    sprintf (buffer + strlen (buffer), " %d", r);
    493 		    break;
    494 		  }
    495 	    }
    496 	}
    497       fprintf (out, "%s\n", buffer);
    498     }
    499 }
    500 
    501 void
    503 print_results (void)
    504 {
    505   state_number i;
    506 
    507   /* We used to use just .out if SPEC_NAME_PREFIX (-p) was used, but
    508      that conflicts with Posix.  */
    509   FILE *out = xfopen (spec_verbose_file, "w");
    510 
    511   reduce_output (out);
    512   grammar_rules_partial_print (out,
    513 			       _("Rules useless in parser due to conflicts"),
    514                                  rule_useless_in_parser_p);
    515   conflicts_output (out);
    516 
    517   print_grammar (out);
    518 
    519   /* If the whole state item sets, not only the kernels, are wanted,
    520      `closure' will be run, which needs memory allocation/deallocation.   */
    521   if (report_flag & report_itemsets)
    522     new_closure (nritems);
    523   /* Storage for print_reductions.  */
    524   no_reduce_set =  bitset_create (ntokens, BITSET_FIXED);
    525   for (i = 0; i < nstates; i++)
    526     print_state (out, states[i]);
    527   bitset_free (no_reduce_set);
    528   if (report_flag & report_itemsets)
    529     free_closure ();
    530 
    531   xfclose (out);
    532 }
    533