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