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
41static graph static_graph;
42static FILE *fgraph = NULL;
43
44
45/*----------------------------.
46| Construct the node labels.  |
47`----------------------------*/
48
49static void
50print_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
122static void
123print_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
168static void
169print_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
195void
196print_graph (void)
197{
198  state_number i;
199
200  /* Output file.  */
201  fgraph = xfopen (spec_graph_file, "w");
202
203  new_graph (&static_graph);
204
205  static_graph.display_edge_labels = yes;
206
207  static_graph.port_sharing = no;
208  static_graph.finetuning = yes;
209  static_graph.priority_phase = yes;
210  static_graph.splines = yes;
211
212  static_graph.crossing_weight = median;
213
214  /* Output graph options. */
215  open_graph (fgraph);
216  output_graph (&static_graph, fgraph);
217
218  /* Output nodes and edges. */
219  new_closure (nritems);
220  for (i = 0; i < nstates; i++)
221    print_state (states[i]);
222  free_closure ();
223
224  /* Close graph. */
225  close_graph (&static_graph, fgraph);
226  xfclose (fgraph);
227}
228