00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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);
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);
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
00207 template <typename DFirstCursor>
00208 void dot(ostream &out, DFirstCursor x, DFirstCursor y = DFirstCursor())
00209 {
00210 DFA_dot<> output(out);
00211 dot(output, x, y);
00212 }
00213
00214
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
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
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263 }
00264
00265 #endif // ASTL_DOT_ALGORITHM
00266
00267