]>
git.saurik.com Git - bison.git/blob - src/graphviz.c
1 /* Output Graphviz specification of a state machine generated by Bison.
3 Copyright (C) 2006-2007, 2009-2012 Free Software Foundation, Inc.
5 This file is part of Bison, the GNU Compiler Compiler.
7 This program 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 3 of the License, or
10 (at your option) any later version.
12 This program 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.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 /* Written by Paul Eggert and Satya Kiran Popuri. */
32 /* Return an unambiguous printable representation for NAME, suitable
33 for C strings. Use slot 2 since the user may use slots 0 and 1. */
36 quote (char const *name
)
38 return quotearg_n_style (2, c_quoting_style
, name
);
42 start_graph (FILE *fout
)
45 _("// Generated by %s.\n"
46 "// Report bugs to <%s>.\n"
47 "// Home page: <%s>.\n"
55 quote (grammar_file
));
57 " node [fontname = courier, shape = box, colorscheme = paired6]\n"
58 " edge [fontname = courier]\n"
63 output_node (int id
, char const *label
, FILE *fout
)
65 fprintf (fout
, " %d [label=\"%s\"]\n", id
, label
);
69 output_edge (int source
, int destination
, char const *label
,
70 char const *style
, FILE *fout
)
72 fprintf (fout
, " %d -> %d [style=%s", source
, destination
, style
);
74 fprintf (fout
, " label=%s", quote (label
));
79 escape (char const *name
)
81 char *q
= quote (name
);
82 q
[strlen (q
) - 1] = '\0';
87 no_reduce_bitset_init (state
const *s
, bitset
*no_reduce_set
)
90 *no_reduce_set
= bitset_create (ntokens
, BITSET_FIXED
);
91 bitset_zero (*no_reduce_set
);
92 FOR_EACH_SHIFT (s
->transitions
, n
)
93 bitset_set (*no_reduce_set
, TRANSITION_SYMBOL (s
->transitions
, n
));
94 for (n
= 0; n
< s
->errs
->num
; ++n
)
95 if (s
->errs
->symbols
[n
])
96 bitset_set (*no_reduce_set
, s
->errs
->symbols
[n
]->number
);
100 conclude_red (struct obstack
*out
, int source
, rule_number ruleno
,
101 bool enabled
, bool first
, FILE *fout
)
103 /* If no lookahead tokens were valid transitions, this reduction is
104 actually hidden, so cancel everything. */
106 return (void) obstack_finish0 (out
);
109 char const *ed
= enabled
? "" : "d";
110 char const *color
= enabled
? ruleno
? "3" : "1" : "5";
112 /* First, build the edge's head. The name of reduction nodes is "nRm",
113 with n the source state and m the rule number. This is because we
114 don't want all the reductions bearing a same rule number to point to
115 the same state, since that is not the desired format. */
116 fprintf (fout
, " %1$d -> \"%1$dR%2$d%3$s\" [",
119 /* (The lookahead tokens have been added to the beginning of the
120 obstack, in the caller function.) */
121 if (! obstack_empty_p (out
))
123 char *label
= obstack_finish0 (out
);
124 fprintf (fout
, "label=\"[%s]\", ", label
);
125 obstack_free (out
, label
);
128 /* Then, the edge's tail. */
129 fprintf (fout
, "style=solid]\n");
131 /* Build the associated diamond representation of the target rule. */
132 fprintf (fout
, " \"%dR%d%s\" [label=\"",
135 fprintf (fout
, "R%d", ruleno
);
137 fprintf (fout
, "Acc");
139 fprintf (fout
, "\", fillcolor=%s, shape=diamond, style=filled]\n",
145 print_token (struct obstack
*out
, bool first
, char const *tok
)
147 char const *q
= escape (tok
);
150 obstack_sgrow (out
, ", ");
151 obstack_sgrow (out
, q
);
156 output_red (state
const *s
, reductions
const *reds
, FILE *fout
)
158 bitset no_reduce_set
;
160 int source
= s
->number
;
162 /* Two obstacks are needed: one for the enabled reductions, and one
163 for the disabled reductions, because in the end we want two
164 separate edges, even though in most cases only one will actually
169 no_reduce_bitset_init (s
, &no_reduce_set
);
170 obstack_init (&dout
);
171 obstack_init (&eout
);
173 for (j
= 0; j
< reds
->num
; ++j
)
175 bool defaulted
= false;
178 rule_number ruleno
= reds
->rules
[j
]->number
;
179 rule
*default_reduction
= NULL
;
181 if (yydefact
[s
->number
] != 0)
182 default_reduction
= &rules
[yydefact
[s
->number
] - 1];
184 /* Build the lookahead tokens lists, one for enabled transitions and one
185 for disabled transistions. */
186 if (default_reduction
&& default_reduction
== reds
->rules
[j
])
188 if (reds
->lookahead_tokens
)
191 for (i
= 0; i
< ntokens
; i
++)
192 if (bitset_test (reds
->lookahead_tokens
[j
], i
))
194 if (bitset_test (no_reduce_set
, i
))
195 firstd
= print_token (&dout
, firstd
, symbols
[i
]->tag
);
199 firste
= print_token (&eout
, firste
, symbols
[i
]->tag
);
200 bitset_set (no_reduce_set
, i
);
205 /* Do the actual output. */
206 conclude_red (&dout
, source
, ruleno
, false, firstd
, fout
);
207 conclude_red (&eout
, source
, ruleno
, true, firste
&& !defaulted
, fout
);
209 obstack_free (&dout
, 0);
210 obstack_free (&eout
, 0);
211 bitset_free (no_reduce_set
);
215 finish_graph (FILE *fout
)