hi, Here is a bare bones implementation (mostly a weekend hack) of graphviz (dot) format output for Bison; The code is very similiar to current VCG implementation. I ran it against the calc++ example..the dot file is attached here, and this graph is generated by running it thru `dot' with the -Tpng option: http://cs.uic.edu/~spopuri/la.png
Comments please.. thanks, satya.
calc++-parser.dot
Description: MS-Word document
/* Output Graphviz specification of a state machine genetated by Bison.
Copyright (C) 2001, 2002, 2005, 2006 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
#include <config.h>
#include "system.h"
#include <quotearg.h>
#include "graphviz.h"
#include "graphviz_defaults.h"
/** Local functions */
static void output_color(enum color, FILE *);
static void output_node_attributes(struct node_attributes *, FILE *);
static void output_edge_attributes(struct edge_attributes *, FILE *);
static void output_graph_attributes(struct graph_attributes *, FILE *);
static void new_node_attributes(struct node_attributes *);
static void new_edge_attributes(struct edge_attributes *);
static void new_graph_attributes(struct graph_attributes *);
static bool output_separator(bool, FILE *);
/* Return an unambiguous printable representated, for NAME, suitable
for C strings. Use slot 2 since the user may use slots 0 and 1.
*/
static char const *
quote (char const *name)
{
return quotearg_n_style (2, c_quoting_style, name);
}
void
new_graph (graph *g)
{
g->title = G_TITLE;
new_graph_attributes(&g->graph_attributes);
/* Some default attributes for all nodes and edges */
new_node_attributes(&g->node_attributes);
g->node_attributes.shape = circle;
g->node_attributes.fillcolor = white;
g->node_attributes.textcolor = blue;
g->node_attributes.bordercolor = black;
new_edge_attributes(&g->edge_attributes);
g->edge_attributes.weight=2.0;
g->edge_attributes.color=black;
g->edge_attributes.textcolor=black;
g->edge_attributes.arrowstyle=normal;
}
void
open_graph (FILE *fout)
{
fprintf(fout,"digraph ");
}
void
output_graph(graph *g, FILE *fout)
{
bool atleastone= false;
/* output the graph attributes first */
if(g->title != G_TITLE)
{
fprintf(fout,"%s {\n",g->title);
}
fprintf(fout,"\tgraph");
output_graph_attributes(&g->graph_attributes,fout);
fprintf(fout,"\n");
/* Done with graph params; output node and edge params */
fprintf(fout,"\tnode");
output_node_attributes(&g->node_attributes,fout);
fprintf(fout,"\n");
fprintf(fout,"\tedge");
output_edge_attributes(&g->edge_attributes,fout);
fprintf(fout,"\n");
/*An extra new line to separate the states */
fprintf(fout,"\n");
}
void
close_graph(FILE *fout)
{
fprintf(fout,"\n}");
}
/** Create a new node */
void
new_node(node *n)
{
n->title = N_TITLE;
new_node_attributes(&n->attrs);
}
void
open_node(FILE *fout)
{
fprintf(fout,"\t");
}
void
output_node(node *n, FILE *fout)
{
/** Ouput the node name and then properties */
fprintf(fout, "%s",n->title);
output_node_attributes(&n->attrs,fout);
}
void
close_node(FILE *fout)
{
fprintf(fout,"\n");
}
/** Create a new edge. */
void
new_edge(edge *e)
{
e->sourcename = E_SOURCENAME;
e->targetname = E_TARGETNAME;
new_edge_attributes(&e->attrs);
}
void
open_edge(FILE *fout)
{
fprintf(fout,"\t");
}
void
output_edge(edge *e, FILE *fout)
{
fprintf(fout,"%s -> %s",e->sourcename,e->targetname);
output_edge_attributes(&e->attrs,fout);
}
void
close_edge(FILE *fout)
{
fprintf(fout, "\n");
}
void
output_color(enum color color, FILE *fout)
{
switch(color)
{
case black: fprintf(fout, "black"); break;
case red: fprintf(fout, "red"); break;
case blue: fprintf(fout, "blue"); break;
case green: fprintf(fout, "green"); break;
case white:
default: fprintf(fout, "white"); break;
}
}
void
output_node_attributes(struct node_attributes *na, FILE *fout)
{
bool atleastone = false;
fprintf(fout," [");
/** Output the label */
if(na->label != NA_LABEL)
{
fprintf(fout,"label=%s", quote(na->label));
atleastone = true;
}
/** Output shape attribute. */
if(na->shape != NA_SHAPE)
{
atleastone = output_separator(atleastone,fout);
fprintf(fout,"shape=");
switch(na->shape)
{
case box: fprintf(fout,"box");
break;
case doublecircle: fprintf(fout, "doublecircle");
break;
case circle:
default: fprintf(fout,"circle");
break;
}
}
/** Output fillcolor. */
if(na->fillcolor != NA_FILLCOLOR)
{
atleastone = output_separator(atleastone,fout);
fprintf(fout,"fillcolor=");
output_color(na->fillcolor,fout);
}
/** Output node textcolor. */
if(na->textcolor != NA_FONTCOLOR)
{
atleastone = output_separator(atleastone,fout);
fprintf(fout,"fontcolor=");
output_color(na->textcolor, fout);
}
/** Output node border color. */
if(na->bordercolor != NA_COLOR)
{
atleastone = output_separator(atleastone,fout);
fprintf(fout,"color=");
output_color(na->bordercolor, fout);
}
/** Close the node attributes. */
fprintf(fout, "];");
}
void
output_edge_attributes(struct edge_attributes *ea, FILE *fout){
bool atleastone = false;
/** Output generic edge properties. */
fprintf(fout, " [");
/** Edge label */
if(ea->label != EA_LABEL)
{
fprintf(fout, "label=%s",quote(ea->label));
atleastone = true;
}
/** Edge weight. */
if(ea->weight != EA_WEIGHT)
{
atleastone = output_separator(atleastone,fout);
fprintf(fout, "weight=%2.1f", ea->weight);
}
/** Edge colors. */
if(ea->color != EA_COLOR)
{
atleastone = output_separator(atleastone,fout);
fprintf(fout, "fontcolor=");
output_color(ea->color,fout);
}
if(ea->textcolor != EA_FONTCOLOR)
{
atleastone = output_separator(atleastone,fout);
fprintf(fout, "color=");
output_color(ea->textcolor, fout);
}
/** Arrow style. */
if(ea->arrowstyle != EA_ARROWSTYLE)
{
atleastone = output_separator(atleastone,fout);
fprintf(fout, "arrowhead=");
switch(ea->arrowstyle)
{
case empty: fprintf(fout, "empty" ); break;
case vee: fprintf(fout, "vee" ); break;
case normal:
default: fprintf(fout, "normal"); break;
}
}
/** Close the general edge properties */
fprintf(fout, "];");
}
void
output_graph_attributes(struct graph_attributes *ga, FILE *fout)
{
bool atleastone = false;
fprintf(fout," [");
if(ga->orientation != G_ORIENTATION)
{
fprintf(fout,"rankdir=");
switch(ga->orientation)
{
case top_to_bottom: fprintf(fout,"TB");
break;
case right_to_left: fprintf(fout,"RL");
break;
case bottom_to_top: fprintf(fout,"BT");
break;
case left_to_right:
default: fprintf(fout,"LR");
break;
}
atleastone = true;
}
if(ga->splines != G_SPLINES)
{
atleastone = output_separator(atleastone,fout);
fprintf(fout,"splines=");
if(ga->splines == yes)
fprintf(fout,"true");
else
fprintf(fout,"false");
}
if(ga->center != G_CENTER)
{
atleastone = output_separator(atleastone,fout);
fprintf(fout, "center=");
if(ga->center == yes)
fprintf(fout,"true");
else
fprintf(fout,"false");
}
if(ga->landscape != G_LANDSCAPE)
{
atleastone = output_separator(atleastone,fout);
fprintf(fout,"landscape=");
if(ga->landscape == yes)
fprintf(fout,"true");
else
fprintf(fout,"false");
}
fprintf(fout,"];");
}
void
new_node_attributes(struct node_attributes *na)
{
na->label = NA_LABEL;
na->shape = NA_SHAPE;
na->fillcolor = NA_FILLCOLOR;
na->textcolor = NA_FONTCOLOR;
na->bordercolor = NA_COLOR;
}
void
new_edge_attributes(struct edge_attributes *ea)
{
ea->label = EA_LABEL;
ea->weight = EA_WEIGHT;
ea->color = EA_COLOR;
ea->textcolor = EA_FONTCOLOR;
ea->arrowstyle= EA_ARROWSTYLE;
}
void new_graph_attributes(struct graph_attributes *ga){
ga->orientation = G_ORIENTATION;
ga->splines = G_SPLINES;
ga->center = G_CENTER;
ga->landscape = G_LANDSCAPE;
}
bool
output_separator(bool atleastone, FILE *fout)
{
if(atleastone)
{
fprintf(fout,", ");
}
return true;
}
/* Graphviz description handler for Bison. Some default values. Copyright (C) 2001, 2002, 2005, 2006 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. Bison is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. Bison is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Bison; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef GRAPHVIZ_DEFAULTS_H_ # define GRAPHVIZ_DEFAULTS_H_ /* Graph defaults. */ # define G_TITLE NULL # define G_ORIENTATION top_to_bottom # define G_SPLINES (-1) /* Default undefined. */ # define G_CENTER no # define G_LANDSCAPE no /* Nodes defaults. */ # define N_TITLE NULL /* Mandatory. */ # define NA_LABEL NULL # define NA_SHAPE ellipse # define NA_COLOR black # define NA_FILLCOLOR lightgrey # define NA_FONTCOLOR black /* Edge defaults. */ # define E_SOURCENAME NULL /* Mandatory. */ # define E_TARGETNAME NULL /* Mandatory. */ # define EA_LABEL NULL # define EA_WEIGHT 1.0 # define EA_COLOR black # define EA_FONTCOLOR black # define EA_ARROWSTYLE normal #endif /* not Graphviz_DEFAULTS_H_ */
/* Definitions for Graphviz output of state machines genetated by Bison.
Copyright (C) 2001, 2002, 2005, 2006 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
#ifndef GRAPHVIZ_H_
# define GRAPHVIZ_H_
#include <stdio.h>
/** Graph orientations supported by GraphViz. */
enum graph_direction
{
top_to_bottom,
bottom_to_top,
left_to_right,
right_to_left
};
/** Some node shapes supported by GraphViz. */
enum shape
{
box,
ellipse,
circle,
doublecircle
};
/** Some basic colors from the X11 color scheme. */
enum color
{
white,
black,
blue,
red,
green,
lightgrey
};
/** Some arrow types supported by GraphViz. */
enum arrow_type
{
normal,
empty,
vee
};
enum decision
{
yes,
no
};
struct node_attributes
{
const char *label;
enum shape shape;
enum color fillcolor;
enum color textcolor;
enum color bordercolor;
};
struct edge_attributes
{
const char *label;
double weight;
enum color color;
enum color textcolor;
enum arrow_type arrowstyle;
};
struct graph_attributes
{
enum graph_direction orientation;
enum decision splines;
enum decision center;
enum decision landscape;
};
struct edge
{
const char *sourcename;
const char *targetname;
struct edge_attributes attrs;
};
struct node
{
const char *title;
struct node_attributes attrs;
};
struct graph
{
const char *title;
/** General properties of a graph. */
struct graph_attributes graph_attributes;
/** General node and edge attributes that apply to the entire graph. */
struct node_attributes node_attributes;
struct edge_attributes edge_attributes;
};
typedef struct graph graph;
typedef struct node node;
typedef struct edge edge;
void new_graph(graph *g);
void new_node(node *n);
void new_edge(edge *e);
void open_node(FILE *fout);
void output_node(node *n, FILE *fout);
void close_node(FILE *fout);
void open_edge(FILE *fout);
void output_edge(edge *e, FILE *fout);
void close_edge(FILE *fout);
/** Start a DOT graph description */
void open_graph(FILE *fout);
/** output a graph description */
void output_graph(graph *g, FILE *fout);
/** Close a graph description */
void close_graph(FILE *fout);
#endif
Index: Makefile.am
===================================================================
RCS file: /sources/bison/bison/src/Makefile.am,v
retrieving revision 1.71
diff -u -r1.71 Makefile.am
--- Makefile.am 15 Sep 2006 18:59:40 -0000 1.71
+++ Makefile.am 28 Sep 2006 20:27:46 -0000
@@ -65,8 +65,8 @@
system.h \
tables.h tables.c \
uniqstr.c uniqstr.h \
- vcg.c vcg.h \
- vcg_defaults.h
+ graphviz.c graphviz.h \
+ graphviz_defaults.h
EXTRA_bison_SOURCES = scan-code.l scan-skel.l scan-gram.l
Index: files.c
===================================================================
RCS file: /sources/bison/bison/src/files.c,v
retrieving revision 1.96
diff -u -r1.96 files.c
--- files.c 9 Jul 2006 03:44:51 -0000 1.96
+++ files.c 28 Sep 2006 20:27:46 -0000
@@ -323,7 +323,7 @@
if (graph_flag)
{
if (! spec_graph_file)
- spec_graph_file = concat2 (all_but_tab_ext, ".vcg");
+ spec_graph_file = concat2 (all_but_tab_ext, ".dot");
name[names++] = spec_graph_file;
}
Index: print_graph.c
===================================================================
RCS file: /sources/bison/bison/src/print_graph.c,v
retrieving revision 1.61
diff -u -r1.61 print_graph.c
--- print_graph.c 10 Jun 2006 03:02:23 -0000 1.61
+++ print_graph.c 28 Sep 2006 20:27:46 -0000
@@ -36,7 +36,7 @@
#include "reader.h"
#include "state.h"
#include "symtab.h"
-#include "vcg.h"
+#include "graphviz.h"
static graph static_graph;
static FILE *fgraph = NULL;
@@ -127,7 +127,7 @@
transitions *trans = s->transitions;
reductions *reds = s->reductions;
- static char buff[10];
+ static char buff[16];
edge e;
if (!trans->num && !reds)
@@ -141,19 +141,17 @@
new_edge (&e);
- if (s->number > s1->number)
- e.type = back_edge;
- open_edge (&e, fgraph);
+ open_edge (fgraph);
/* The edge source is the current node. */
e.sourcename = node_name;
- sprintf (buff, "%d", s1->number);
+ sprintf (buff, "state_%d", s1->number);
e.targetname = buff;
/* Shifts are blue, gotos are green, and error is red. */
if (TRANSITION_IS_ERROR (trans, i))
- e.color = red;
+ e.attrs.color = red;
else
- e.color = TRANSITION_IS_SHIFT (trans, i) ? blue : green;
- e.label = symbols[sym]->tag;
+ e.attrs.color = TRANSITION_IS_SHIFT (trans, i) ? blue : green;
+ e.attrs.label = symbols[sym]->tag;
output_edge (&e, fgraph);
close_edge (fgraph);
}
@@ -168,18 +166,21 @@
static void
print_state (state *s)
{
- static char name[10];
+ static char name[16];
struct obstack node_obstack;
node n;
/* The labels of the nodes are their the items. */
obstack_init (&node_obstack);
new_node (&n);
- sprintf (name, "%d", s->number);
+ sprintf (name, "state_%d", s->number);
n.title = name;
+ if(s->number == final_state->number)
+ n.attrs.shape = doublecircle;
+
print_core (&node_obstack, s);
obstack_1grow (&node_obstack, '\0');
- n.label = obstack_finish (&node_obstack);
+ n.attrs.label = obstack_finish (&node_obstack);
open_node (fgraph);
output_node (&n, fgraph);
@@ -201,15 +202,12 @@
fgraph = xfopen (spec_graph_file, "w");
new_graph (&static_graph);
+ static_graph.title = "Automaton";
+ static_graph.graph_attributes.orientation = left_to_right;
+ static_graph.graph_attributes.splines = yes;
+ static_graph.graph_attributes.center = yes;
+ static_graph.graph_attributes.landscape = yes;
- static_graph.display_edge_labels = yes;
-
- static_graph.port_sharing = no;
- static_graph.finetuning = yes;
- static_graph.priority_phase = yes;
- static_graph.splines = yes;
-
- static_graph.crossing_weight = median;
/* Output graph options. */
open_graph (fgraph);
@@ -222,6 +220,6 @@
free_closure ();
/* Close graph. */
- close_graph (&static_graph, fgraph);
+ close_graph (fgraph);
xfclose (fgraph);
}
