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