stream.h

00001 /*
00002  * ASTL - the Automaton Standard Template Library.
00003  * C++ generic components for Finite State Automata handling.
00004  * Copyright (C) 2000-2005 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_STREAM_H
00023 #define ASTL_STREAM_H
00024 
00025 #include <astl.h>
00026 #include <iostream>
00027 #include <set>
00028 #include <map>
00029 #include <stack>
00030 #include <utility>
00031 
00032 using namespace std;
00033 
00034 #if (__GNUG__ && __GNUG__ > 2)
00035 using namespace rel_ops;
00036 #endif
00037 
00038 namespace astl {
00039 
00040 template <typename Tag = empty>
00041 class DFA_stream
00042 {
00043 public:
00044   typedef Tag        tag_type;
00045   typedef int        state_type;
00046   typedef state_type State;
00047   struct bool_reference;
00048   friend struct bool_reference;
00049 
00050 protected:
00051   ostream &out;
00052   set<state_type> F;
00053   state_type count;
00054   map<state_type, tag_type> T;
00055 
00056 public:
00057   static const state_type null_state = 0;
00058 
00059   DFA_stream(ostream &output)
00060     : out(output), count(0)
00061   { }
00062 
00063   state_type new_state() { return ++count;  }
00064 
00065   tag_type& tag(state_type q) { return tag_(q, tag_type()); }
00066 
00067   struct bool_reference
00068   {
00069     state_type q;
00070     DFA_stream &dfa;
00071 
00072     bool_reference(state_type p, DFA_stream &a)
00073       : q(p), dfa(a)
00074     { }
00075 
00076     bool_reference& operator=(bool b) {
00077       if (b == true) dfa.F.insert(q);
00078       else dfa.F.erase(q);
00079       return *this;
00080     }
00081   };
00082 
00083   bool_reference final(state_type q) {
00084     return bool_reference(q, *this);
00085   }
00086 
00087   template <typename Alphabet>
00088   void set_trans(state_type q, const Alphabet &a, state_type p) {
00089     write_state(q);
00090     out << '\t' << a << '\t';
00091     write_state(p);
00092     write_tag(q);
00093     write_tag(p);
00094     out << endl;
00095   }
00096 
00097   void set_trans(state_type q, const char& a, state_type p) {
00098     set_trans(q, (int) a, p);
00099   }
00100 
00101   void set_trans(state_type q, const unsigned char& a, state_type p) {
00102     set_trans(q, (int) a, p);
00103   }
00104 
00105   void set_trans(state_type q, const string& a, state_type p) {
00106     write_state(q);
00107     out << "\t\"" << a << "\"\t";
00108     write_state(p);
00109     write_tag(q);
00110     write_tag(p);
00111     out << endl;
00112   }
00113 
00114 protected:
00115   template <typename TagType>
00116   tag_type& tag_(state_type q, const TagType&) {
00117     return T[q];
00118   }
00119 
00120   tag_type& tag_(state_type, const empty&) {
00121     static tag_type bogus;
00122     return bogus;
00123   }
00124 
00125   void write_state(state_type q) {
00126     // final states have negative ID:
00127     out << (F.find(q) != F.end() ? -q : q);
00128   }
00129 
00130   void write_tag(state_type q) {
00131     write_tag(q, tag_type());
00132   }
00133   
00134   template <typename TagType>
00135   void write_tag(state_type q, const TagType&)
00136   { 
00137     // output tag if q is in the tag mapping:
00138     typename map<state_type, tag_type>::iterator i = T.find(q);
00139     if (i != T.end()) {
00140       out << '\t' << i->second;
00141       T.erase(i);
00142     }    
00143   }
00144 
00145   void write_tag(state_type q, const string&)
00146   { 
00147     // output tag if q is in the tag mapping:
00148     typename map<state_type, tag_type>::iterator i = T.find(q);
00149     if (i != T.end()) {
00150       out << "\t\"" << i->second << '"';
00151       T.erase(i);
00152     }    
00153   }
00154 
00155   // nothing to do with empty tags:
00156   void write_tag(state_type, const empty&)
00157   { }
00158 };
00159 
00160 template <typename Tag>
00161 const typename DFA_stream<Tag>::state_type DFA_stream<Tag>::null_state;
00162 
00163 template <typename DFirstC>
00164 inline
00165 ostream& dump(ostream &out, DFirstC first, DFirstC last = DFirstC())
00166 {
00167   DFA_stream<> output(out); // empty tag
00168   clone(output, first);
00169   return out;
00170 }
00171 
00172 template <typename DFirstCursor>
00173 inline
00174 ostream& full_dump(ostream &out, DFirstCursor first, DFirstCursor last = DFirstCursor())
00175 {
00176   DFA_stream<typename DFirstCursor::tag_type> output(out);
00177   clone(output, first);
00178   return out;
00179 }
00180 
00181 template <typename CharType>
00182 struct read_char : public binary_function<istream, CharType, void>
00183 {
00184   void operator()(istream &in, CharType& x) const {
00185     in >> x;
00186   }
00187 };
00188 
00189 template < >
00190 struct read_char<unsigned char> 
00191   : public binary_function<istream, unsigned char, void>
00192 {
00193   void operator()(istream &in, unsigned char& x) const {
00194     int tmp;
00195     in >> tmp;
00196     x = (unsigned char) tmp;
00197   }
00198 };
00199 
00200 template < >
00201 struct read_char<char> 
00202   : public binary_function<istream, char, void>
00203 {
00204   void operator()(istream &in, char& x) const {
00205     int tmp;
00206     in >> tmp;
00207     x = (char) tmp;
00208   }
00209 };
00210 
00211 template < >
00212 struct read_char<string> 
00213   : public binary_function<istream, string, void>
00214 {
00215   void operator()(istream &in, string& x) const {
00216     x.erase(x.begin(), x.end());   // VC++ does not implement clear()
00217     char c;
00218     for(c = '\0'; c != '"'; in.get(c));
00219     for(in.get(c); c != '"'; in.get(c))
00220       x += c;
00221   }
00222 };
00223 
00224 template <typename FA>
00225 class istream_cursor : public dfirst_cursor_concept
00226 {
00227 public:
00228   typedef typename FA::char_traits        char_traits;
00229   typedef typename char_traits::char_type char_type;
00230   typedef int                             state_type;
00231   typedef typename FA::tag_type           tag_type;
00232   typedef istream_cursor<FA>              self;
00233 
00234   istream_cursor()               // end of range
00235     : in(cin)
00236   { }
00237 
00238   istream_cursor(istream &input) // start of range
00239     : in(input), has_poped(false) { 
00240     forward();
00241   }
00242 
00243   state_type src() const { return s.top().q;  }
00244   state_type aim() const { return s.top().p;  }
00245 
00246   bool operator==(const self &x) const { // test for the end of range
00247     return s == x.s;
00248   }
00249 
00250   bool operator!= (const self &x) const { return !(*this == x); }
00251 
00252   bool src_final() const { return s.top().q < 0;  }
00253   bool aim_final() const { return s.top().p < 0;  }
00254 
00255   char_type letter() const { return s.top().a; }
00256 
00257   bool forward() 
00258   {
00259     if (in.eof()) {
00260       if (!s.empty()) s.pop();
00261       return s.empty();
00262     }
00263 
00264     if (has_poped) {
00265       if (s.top().q == t.q) {
00266         s.top() = t;
00267         has_poped = false;
00268       }
00269       else 
00270         s.pop();
00271     }
00272     else {
00273       in >> t.q;
00274 #if defined(__GNUG__) && __GNUG__ >= 3
00275       if (in.eof())
00276         return false;
00277 #endif
00278       read_char<char_type>()(in, t.a);
00279       in >> t.p;
00280       if (s.empty() || s.top().p == t.q) {
00281         read_tag(t.q, tag_type());
00282         read_tag(t.p, tag_type());
00283         s.push(t);
00284       }
00285       else 
00286         has_poped = true;
00287     }
00288     return !has_poped;
00289   }
00290 
00291   tag_type src_tag() { return T[s.top().q]; }
00292   tag_type aim_tag() { return T[s.top().p]; }
00293 
00294 protected:
00295   struct transition 
00296   {
00297     state_type q, p;
00298     char_type a;
00299     bool operator==(const transition &x) const {
00300       return q == x.q && p == x.p && a == x.a;
00301     }
00302   };
00303 
00304   istream &in;
00305   stack<transition> s;
00306   transition t;
00307   bool has_poped;
00308   mutable map<state_type, tag_type> T;
00309 
00310   template <typename TagType>
00311   void read_tag(state_type q, const TagType&) { 
00312     if (T.find(q) == T.end()) {
00313       tag_type tmp;
00314       read_char<tag_type>()(in, tmp);
00315       T.insert(make_pair(q, tmp));
00316     }
00317   }
00318 
00319   void read_tag(state_type, const empty&)
00320   { }
00321 };
00322 
00323 template <typename FA>
00324 inline
00325 istream_cursor<FA> istreamc(istream &in, const FA&)
00326 {
00327   return istream_cursor<FA>(in);
00328 }
00329 
00330 template <typename DFA>
00331 inline
00332 void restore(DFA &a, istream &in)
00333 {
00334   a.initial(clone(a, istreamc(in, a)));
00335 }
00336 
00479 } // namespace astl
00480 
00481 #endif // ASTL_STREAM_ALGORITHMS

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