]> git.saurik.com Git - bison.git/blob - src/print_graph.c
Use some of gnulib's new modules, taken from coreutils.
[bison.git] / src / print_graph.c
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 lookahead tokens. */
92 if (report_flag & report_lookahead_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->lookahead_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->lookahead_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 \f
194
195 void
196 print_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 }