]> git.saurik.com Git - bison.git/blob - src/print_graph.c
* src/print_graph.c (quote): New.
[bison.git] / src / print_graph.c
1 /* Output a VCG description on generated parser, for Bison,
2 Copyright 2001 Free Software Foundation, Inc.
3
4 This file is part of Bison, the GNU Compiler Compiler.
5
6 Bison is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 Bison is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Bison; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 #include "system.h"
22 #include "xalloc.h"
23 #include "files.h"
24 #include "gram.h"
25 #include "LR0.h"
26 #include "lalr.h"
27 #include "conflicts.h"
28 #include "complain.h"
29 #include "getargs.h"
30 #include "state.h"
31 #include "reader.h"
32 #include "obstack.h"
33 #include "print_graph.h"
34 #include "vcg.h"
35 #include "quotearg.h"
36
37 static graph_t graph;
38
39 /* Return an unambiguous printable representated, allocated in slot 0,
40 for NAME, suitable for C strings. */
41 static char const *
42 quote (char const *name)
43 {
44 return quotearg_n_style (0, escape_quoting_style, name);
45 }
46
47 /* This part will construct the label of nodes. */
48 static void
49 print_core (int state)
50 {
51 int i;
52 int k;
53 int rule;
54 core *statep;
55 short *sp;
56 short *sp1;
57
58 statep = state_table[state];
59 k = statep->nitems;
60
61 if (k == 0)
62 return;
63
64 obstack_sgrow (&graph_obstack, "\t\tlabel:\t\"");
65
66 for (i = 0; i < k; i++)
67 {
68 if (i)
69 obstack_sgrow (&graph_obstack, "\\n");
70
71 sp1 = sp = ritem + statep->items[i];
72
73 while (*sp > 0)
74 sp++;
75
76 rule = -(*sp);
77
78 obstack_fgrow1 (&graph_obstack, "%d: ", rule);
79 obstack_fgrow1 (&graph_obstack, " %s -> ", quote (tags[rlhs[rule]]));
80
81 for (sp = ritem + rrhs[rule]; sp < sp1; sp++)
82 obstack_fgrow1 (&graph_obstack, "%s ", quote (tags[*sp]));
83
84 obstack_1grow (&graph_obstack, '.');
85
86 while (*sp > 0)
87 obstack_fgrow1 (&graph_obstack, " %s", quote (tags[*sp++]));
88
89 }
90 obstack_sgrow (&graph_obstack, "\"\n");
91 }
92
93 static void
94 print_actions (int state, node_t *node)
95 {
96 int i;
97 int k;
98 int state1;
99 int symbol;
100 shifts *shiftp;
101 errs *errp;
102 reductions *redp;
103 int rule;
104 static char buff[10];
105 edge_t edge;
106
107 shiftp = shift_table[state];
108 redp = reduction_table[state];
109 errp = err_table[state];
110
111 if (!shiftp && !redp)
112 {
113 #if 0
114 if (final_state == state)
115 fprintf (f, " $default\taccept\n");
116 else
117 fprintf (f, " NO ACTIONS\n");
118 #endif
119 return;
120 }
121
122 if (shiftp)
123 {
124 k = shiftp->nshifts;
125
126 for (i = 0; i < k; i++)
127 {
128 if (!shiftp->shifts[i])
129 continue;
130 state1 = shiftp->shifts[i];
131 symbol = accessing_symbol[state1];
132
133 if (ISVAR (symbol))
134 break;
135
136 {
137 new_edge (&edge);
138
139 if (state > state1)
140 edge.type = back_edge;
141 open_edge (&edge, &graph_obstack);
142 edge.sourcename = node->title;
143 sprintf (buff, "%d", state1);
144 edge.targetname = buff;
145 edge.color = (symbol == 0) ? blue : red;
146 /* FIXME: Be aware that quote uses static memory. The string
147 must be output immediately (which is the case here). */
148 edge.label = tags[symbol] ? quote (tags[symbol]) : NULL;
149 output_edge (&edge, &graph_obstack);
150 close_edge (&graph_obstack);
151 }
152 }
153 }
154 else
155 {
156 i = 0;
157 k = 0;
158 }
159
160 if (errp)
161 {
162 int j, nerrs;
163
164 nerrs = errp->nerrs;
165
166 for (j = 0; j < nerrs; j++)
167 {
168 if (!errp->errs[j])
169 continue;
170 symbol = errp->errs[j];
171 }
172 }
173
174 if (consistent[state] && redp)
175 {
176 rule = redp->rules[0];
177 symbol = rlhs[rule];
178 }
179
180 if (i < k)
181 {
182 for (; i < k; i++)
183 {
184 if (!shiftp->shifts[i])
185 continue;
186 state1 = shiftp->shifts[i];
187 symbol = accessing_symbol[state1];
188
189 new_edge (&edge);
190 open_edge (&edge, &graph_obstack);
191 edge.sourcename = node->title;
192 sprintf (buff, "%d", state1);
193 edge.targetname = buff;
194 edge.color = red;
195 edge.label = tags[symbol] ? quote (tags[symbol]) : NULL;
196 output_edge (&edge, &graph_obstack);
197 close_edge (&graph_obstack);
198 }
199 }
200 }
201
202 static void
203 print_state (int state)
204 {
205 static char name[10];
206 node_t node;
207
208 new_node (&node);
209 open_node (&graph_obstack);
210
211 sprintf (name, "%d", state);
212 node.title = name;
213 output_node (&node, &graph_obstack);
214
215 print_core (state); /* node label */
216
217 close_node (&graph_obstack);
218
219 print_actions (state, &node); /* edges */
220 }
221 \f
222
223 void
224 print_graph (void)
225 {
226 int i;
227
228 if (!graph_flag)
229 return;
230 new_graph (&graph);
231
232 /* graph.smanhattan_edges = yes;
233 graph.manhattan_edges = yes; */
234
235 graph.display_edge_labels = yes;
236 graph.layoutalgorithm = 0;
237
238 graph.port_sharing = no;
239 graph.finetuning = yes;
240 graph.straight_phase = yes;
241 graph.priority_phase = yes;
242 graph.splines = yes;
243
244 graph.crossing_weight = median;
245
246 /* Output graph options. */
247 open_graph (&graph_obstack);
248 output_graph (&graph, &graph_obstack);
249
250 for (i = 0; i < nstates; i++)
251 /* Output nodes & edges. */
252 print_state (i);
253
254 /* Close graph. */
255 close_graph (&graph, &graph_obstack);
256 }