dot.h

00001 /*
00002  * ASTL - the Automaton Standard Template Library.
00003  * C++ generic components for Finite State Automata handling.
00004  * Copyright (C) 2000-2003 Vincent Le Maout (vincent.lemaout@chello.fr).
00005  * 
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  * 
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  * 
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 #ifndef ASTL_DOT_H
00023 #define ASTL_DOT_H
00024 
00025 #include <astl.h>
00026 #include <iostream>
00027 #include <string>
00028 #include <cctype>
00029 
00030 using namespace std;
00031 
00032 namespace astl {
00033 
00034 template <typename Tag = empty>
00035 class DFA_dot
00036 {
00037 public:
00038   ostream &out;
00039   typedef unsigned long state_type;
00040   typedef Tag           tag_type;
00041   typedef state_type State;
00042   unsigned long Q, _state_fontsize, _edge_fontsize;
00043   double _ratio, _ranksep;
00044   string _rankdir, _size;
00045   bool _initial;
00046   mutable map<state_type, tag_type> T;
00047 
00048 #ifndef _MSC_VER
00049   static const state_type null_state = 0;
00050 #else
00051   static const state_type null_state;
00052 #endif
00053 
00054   DFA_dot(ostream &output)
00055     : out(output), Q(0), _state_fontsize(14), _edge_fontsize(14),
00056       _ratio(.5), _ranksep(.4), _rankdir("LR"), _initial(true)
00057   { }
00058   
00059   void graph_attributes() {
00060     out << "ratio=" << _ratio << ";" << endl;
00061     out << "rankdir=" << _rankdir << ";" << endl;
00062     out << "ranksep=" << _ranksep << ";" << endl;
00063     if (!_size.empty())
00064       out << "size=\"" << _size << "\";" << endl;
00065   }
00066 
00067   DFA_dot& ratio(float x) {
00068     _ratio = x;
00069     return *this; 
00070   }
00071 
00072   DFA_dot& state_fontsize(unsigned long x) {
00073     _state_fontsize = x;
00074     return *this;
00075   }
00076 
00077   DFA_dot& fontsize(unsigned long x) {
00078     _state_fontsize = x;
00079     _edge_fontsize = x;
00080     return *this;
00081   }
00082 
00083   DFA_dot& edge_fontsize(unsigned long x) {
00084     _edge_fontsize = x;
00085     return *this;
00086   }
00087 
00088   DFA_dot& size(const string &s) {
00089     _size = s;
00090     return *this;
00091   }
00092 
00093   DFA_dot& rankdir(const string &s) {
00094     _rankdir = s;
00095     return *this;
00096   }
00097 
00098   DFA_dot& initial(bool b) {
00099     _initial = b;
00100     return *this;
00101   }
00102 
00103   DFA_dot& ranksep(float f) {
00104     _ranksep = f;
00105     return *this;
00106   }
00107 
00108   bool initial() const { return _initial; }
00109 
00110   unsigned long new_state() { return ++Q; }
00111   
00112   template <typename char_type>
00113   void set_trans(State q, const char_type &a, State p) {
00114     write_state(q); // possibly write tag
00115     out << " -> ";
00116     write_state(p);
00117     out << " [label=\"" << a << "\",fontsize=" 
00118         << _edge_fontsize << "];" << endl;
00119   }
00120 
00121   tag_type& tag(state_type q) { return tag_(q, tag_type()); }
00122 
00123   void set_trans(State q, const char &a, State p) {
00124     write_state(q); // possibly write tag
00125     out << " -> ";
00126     write_state(p);
00127     out << " [label=\"";
00128     if (isgraph(a)) {
00129       if (a == '"' || a == '\\') out << '\\';
00130       out << a;
00131     }
00132     else out << "\\" << (int) a;
00133     out << "\",fontsize=" << _edge_fontsize << "];" << endl;
00134   }
00135 
00136   struct bool_reference
00137   {
00138     State q;
00139     DFA_dot &dfa;
00140 
00141     bool_reference(State p, DFA_dot &a)
00142       : q(p), dfa(a)
00143     { }
00144 
00145     bool_reference& operator=(bool b) {
00146       dfa.out << q << " [shape=circle";
00147       if (b == true) dfa.out << ",style=bold";
00148       dfa.out << ",fontsize=" << dfa._state_fontsize;
00149       write_label(q, typename DFA_dot<Tag>::tag_type());
00150       dfa.out << "];" << endl;
00151       return *this;
00152     }
00153     
00154   protected:
00155     template <typename TagType>
00156     void write_label(state_type q, const TagType&) {
00157       typename map<state_type, tag_type>::iterator i = dfa.T.find(q);
00158       if (i != dfa.T.end()) {
00159         dfa.out << ",label=\"" << i->second << '"';
00160         dfa.T.erase(i);
00161       }
00162     }
00163     
00164     void write_label(state_type, const empty&) 
00165     { }
00166   };
00167 
00168   bool_reference final(State q) {
00169     return bool_reference(q, *this);
00170   }
00171 
00172 protected:
00173   template <typename TagType>
00174   tag_type& tag_(state_type q, const TagType&) {
00175     return T[q];
00176   }
00177 
00178   tag_type& tag_(state_type, const empty&) {
00179     static tag_type bogus;
00180     return bogus;
00181   }
00182 
00183   void write_state(state_type q) { write_state(q, tag_type()); }
00184 
00185   template <typename TagType>
00186   void write_state(state_type q, const TagType&) {
00187     typename map<state_type, tag_type>::iterator i = T.find(q);
00188     out << q;
00189     if (i != T.end()) {
00190       out << " [label=\"" << i->second << "\"];" << endl;
00191       T.erase(i);
00192     }
00193   }
00194 
00195   void write_state(state_type q, const empty&) { out << q; }
00196 };
00197 
00198 #ifndef _MSC_VER
00199 template <typename Tag>
00200 const typename DFA_dot<Tag>::state_type DFA_dot<Tag>::null_state;
00201 #else
00202 template <typename Tag>
00203 const typename DFA_dot<Tag>::state_type DFA_dot<Tag>::null_state = 0;
00204 #endif
00205 
00206 // Output the graph with default configuration:
00207 template <typename DFirstCursor>
00208 void dot(ostream &out, DFirstCursor x, DFirstCursor y = DFirstCursor())
00209 {
00210   DFA_dot<> output(out); // empty tag
00211   dot(output, x, y);
00212 }
00213 
00214 // Output the graph with default configuration:
00215 template <typename DFirstCursor>
00216 void full_dot(ostream &out, DFirstCursor x, DFirstCursor y = DFirstCursor())
00217 {
00218   DFA_dot<typename DFirstCursor::tag_type> output(out);
00219   dot(output, x, y);
00220 }
00221 
00222 // Customized output representation through the DFA_dot object: 
00223 template <typename DFirstCursor, typename Tag>
00224 inline
00225 void dot(DFA_dot<Tag> &output, 
00226          DFirstCursor x, DFirstCursor y = DFirstCursor())
00227 {
00228   output.out << "digraph G {" << endl;
00229   output.graph_attributes();
00230   typename DFA_dot<Tag>::state_type i = clone(output, x, y);
00231   if (output.initial() && i != output.null_state)
00232     output.out << i << " [shape=doublecircle];" << endl;
00233   output.out << "}" << endl;
00234 }
00235 
00236 // template <typename DFirstCursor, typename Tag>
00237 // void dot_(DFA_dot<typename DFirstCursor::tag_type> &output, 
00238 //        DFirstCursor x, DFirstCursor y, const Tag&)
00239 // {
00240 //   output.out << "digraph G {" << endl;
00241 //   output.graph_attributes();
00242 //   typename DFA_dot<typename DFirstCursor::tag_type>::State i = clone(output, x, y);
00243 //   if (output.initial() && i != output.null_state)
00244 //     output.out << i << " [shape=doublecircle];" << endl;
00245 //   output.out << "}" << endl;
00246 // }
00247 
00248 // template <typename DFirstCursor>
00249 // void dot_(DFA_dot<typename DFirstCursor::tag_type> &output, 
00250 //        DFirstCursor x, DFirstCursor y, const empty&)
00251 // {
00252 //   //  output.tags(false);
00253 //   output.out << "digraph G {" << endl;
00254 //   output.graph_attributes();
00255 //   typename DFA_dot<typename DFirstCursor::tag_type>::State i = clone(output, x, y);
00256 //   if (output.initial() && i != output.null_state)
00257 //     output.out << i << " [shape=doublecircle];" << endl;
00258 //   output.out << "}" << endl;
00259 // }
00260 
00261 
00262 
00263 } // namespace astl
00264     
00265 #endif // ASTL_DOT_ALGORITHM
00266 
00267 

Generated on Sun Mar 8 02:41:33 2009 for ASTL by  doxygen 1.5.7.1