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