Home | History | Annotate | Download | only in src
      1 /* Output a VCG description on generated parser, for Bison,
      2 
      3    Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
      4 
      5    This file is part of Bison, the GNU Compiler Compiler.
      6 
      7    Bison is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 2, or (at your option)
     10    any later version.
     11 
     12    Bison is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with Bison; see the file COPYING.  If not, write to
     19    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     20    Boston, MA 02110-1301, USA.  */
     21 
     22 #include <config.h>
     23 #include "system.h"
     24 
     25 #include <quotearg.h>
     26 
     27 #include "LR0.h"
     28 #include "closure.h"
     29 #include "complain.h"
     30 #include "conflicts.h"
     31 #include "files.h"
     32 #include "getargs.h"
     33 #include "gram.h"
     34 #include "lalr.h"
     35 #include "print_graph.h"
     36 #include "reader.h"
     37 #include "state.h"
     38 #include "symtab.h"
     39 #include "vcg.h"
     40 
     41 static graph static_graph;
     42 static FILE *fgraph = NULL;
     43 
     44 
     45 /*----------------------------.
     46 | Construct the node labels.  |
     47 `----------------------------*/
     48 
     49 static void
     50 print_core (struct obstack *oout, state *s)
     51 {
     52   size_t i;
     53   item_number *sitems = s->items;
     54   size_t snritems = s->nitems;
     55 
     56   /* Output all the items of a state, not only its kernel.  */
     57   if (report_flag & report_itemsets)
     58     {
     59       closure (sitems, snritems);
     60       sitems = itemset;
     61       snritems = nritemset;
     62     }
     63 
     64   obstack_fgrow1 (oout, "state %2d\n", s->number);
     65   for (i = 0; i < snritems; i++)
     66     {
     67       item_number *sp;
     68       item_number *sp1;
     69       rule_number r;
     70 
     71       sp1 = sp = ritem + sitems[i];
     72 
     73       while (*sp >= 0)
     74 	sp++;
     75 
     76       r = item_number_as_rule_number (*sp);
     77 
     78       if (i)
     79 	obstack_1grow (oout, '\n');
     80       obstack_fgrow1 (oout, " %s -> ",
     81 		      rules[r].lhs->tag);
     82 
     83       for (sp = rules[r].rhs; sp < sp1; sp++)
     84 	obstack_fgrow1 (oout, "%s ", symbols[*sp]->tag);
     85 
     86       obstack_1grow (oout, '.');
     87 
     88       for (/* Nothing */; *sp >= 0; ++sp)
     89 	obstack_fgrow1 (oout, " %s", symbols[*sp]->tag);
     90 
     91       /* Experimental feature: display the look-ahead tokens. */
     92       if (report_flag & report_look_ahead_tokens)
     93 	{
     94 	  /* Find the reduction we are handling.  */
     95 	  reductions *reds = s->reductions;
     96 	  int redno = state_reduction_find (s, &rules[r]);
     97 
     98 	  /* Print them if there are.  */
     99 	  if (reds->look_ahead_tokens && redno != -1)
    100 	    {
    101 	      bitset_iterator biter;
    102 	      int k;
    103 	      char const *sep = "";
    104 	      obstack_sgrow (oout, "[");
    105 	      BITSET_FOR_EACH (biter, reds->look_ahead_tokens[redno], k, 0)
    106 		{
    107 		  obstack_fgrow2 (oout, "%s%s", sep, symbols[k]->tag);
    108 		  sep = ", ";
    109 		}
    110 	      obstack_sgrow (oout, "]");
    111 	    }
    112 	}
    113     }
    114 }
    115 
    116 
    117 /*---------------------------------------------------------------.
    118 | Output in graph_obstack edges specifications in incidence with |
    119 | current node.                                                  |
    120 `---------------------------------------------------------------*/
    121 
    122 static void
    123 print_actions (state *s, const char *node_name)
    124 {
    125   int i;
    126 
    127   transitions *trans = s->transitions;
    128   reductions *reds = s->reductions;
    129 
    130   static char buff[10];
    131   edge e;
    132 
    133   if (!trans->num && !reds)
    134     return;
    135 
    136   for (i = 0; i < trans->num; i++)
    137     if (!TRANSITION_IS_DISABLED (trans, i))
    138       {
    139 	state *s1 = trans->states[i];
    140 	symbol_number sym = s1->accessing_symbol;
    141 
    142 	new_edge (&e);
    143 
    144 	if (s->number > s1->number)
    145 	  e.type = back_edge;
    146 	open_edge (&e, fgraph);
    147 	/* The edge source is the current node.  */
    148 	e.sourcename = node_name;
    149 	sprintf (buff, "%d", s1->number);
    150 	e.targetname = buff;
    151 	/* Shifts are blue, gotos are green, and error is red. */
    152 	if (TRANSITION_IS_ERROR (trans, i))
    153 	  e.color = red;
    154 	else
    155 	  e.color = TRANSITION_IS_SHIFT (trans, i) ? blue : green;
    156 	e.label = symbols[sym]->tag;
    157 	output_edge (&e, fgraph);
    158 	close_edge (fgraph);
    159       }
    160 }
    161 
    162 
    163 /*-------------------------------------------------------------.
    164 | Output in FGRAPH the current node specifications and exiting |
    165 | edges.                                                       |
    166 `-------------------------------------------------------------*/
    167 
    168 static void
    169 print_state (state *s)
    170 {
    171   static char name[10];
    172   struct obstack node_obstack;
    173   node n;
    174 
    175   /* The labels of the nodes are their the items.  */
    176   obstack_init (&node_obstack);
    177   new_node (&n);
    178   sprintf (name, "%d", s->number);
    179   n.title = name;
    180   print_core (&node_obstack, s);
    181   obstack_1grow (&node_obstack, '\0');
    182   n.label = obstack_finish (&node_obstack);
    183 
    184   open_node (fgraph);
    185   output_node (&n, fgraph);
    186   close_node (fgraph);
    187 
    188   /* Output the edges.  */
    189   print_actions (s, name);
    190 
    191   obstack_free (&node_obstack, 0);
    192 }
    193 
    194 
    196 void
    197 print_graph (void)
    198 {
    199   state_number i;
    200 
    201   /* Output file.  */
    202   fgraph = xfopen (spec_graph_file, "w");
    203 
    204   new_graph (&static_graph);
    205 
    206   static_graph.display_edge_labels = yes;
    207 
    208   static_graph.port_sharing = no;
    209   static_graph.finetuning = yes;
    210   static_graph.priority_phase = yes;
    211   static_graph.splines = yes;
    212 
    213   static_graph.crossing_weight = median;
    214 
    215   /* Output graph options. */
    216   open_graph (fgraph);
    217   output_graph (&static_graph, fgraph);
    218 
    219   /* Output nodes and edges. */
    220   new_closure (nritems);
    221   for (i = 0; i < nstates; i++)
    222     print_state (states[i]);
    223   free_closure ();
    224 
    225   /* Close graph. */
    226   close_graph (&static_graph, fgraph);
    227   xfclose (fgraph);
    228 }
    229