nfa_mmap.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 // Descrition:  
00023 //  ASTL 2.0 Non Determinisic Finite Automaton Class Template NFA_mmap
00024 //  Representation by STL multimap
00025 
00026 #ifndef ASTL_NFA_MMAP_H
00027 #define ASTL_NFA_MMAP_H
00028 
00029 #include <set>            // set<>
00030 #include <map>            // multimap<>
00031 #include <algorithm>      // transform()
00032 #include <utility>        // pair<>
00033 #include <astl.h>
00034 
00035 #if (__GNUG__ && __GNUG__ > 2)
00036 using namespace __gnu_cxx;
00037 #endif
00038 
00039 using namespace std;
00040 
00041 namespace astl {
00042 
00043 template <class CharTraits>
00044 struct nfa_mmap_key_compare 
00045   : public binary_function<typename CharTraits::char_type, 
00046   typename CharTraits::char_type, bool>
00047 {
00048   bool operator()(const typename CharTraits::char_type &x,
00049                   const typename CharTraits::char_type &y) const {
00050     return CharTraits::lt(x, y);
00051   }
00052 };
00053 
00054 template <typename State, typename CharTraits, typename Tag>
00055 struct nfa_mmap_state_data
00056 {
00057   Tag t;
00058   multimap<typename CharTraits::char_type, State, 
00059            nfa_mmap_key_compare<CharTraits> > edges;
00060 };
00061 
00062 // #ifndef _MSC_VER
00063 // Partial specialization for empty tag:
00064 template <typename State, typename CharTraits>
00065 struct nfa_mmap_state_data<State, CharTraits, empty_tag>
00066 {
00067   static empty_tag t; // consistent interface with previous definition
00068   multimap<typename CharTraits::char_type, State, 
00069            nfa_mmap_key_compare<CharTraits> > edges;
00070 };
00071         
00072 template <class State, class Alphabet>
00073 empty_tag nfa_mmap_state_data<State, Alphabet, empty_tag>::t;
00074 // #endif
00075 
00076 template <class _Sigma = plain,
00077           class _Tag   = empty_tag> 
00078 class NFA_mmap : public NFA_concept
00079 {
00080 public:
00081   typedef _Sigma                     char_traits;
00082   typedef typename _Sigma::char_type char_type;
00083   typedef _Tag                       tag_type;
00084   typedef unsigned int               state_type;
00085 
00086   // Backward compatibility:
00087   typedef char_type   Alphabet; 
00088   typedef char_traits Sigma; 
00089   typedef tag_type    Tag;
00090   typedef state_type  State;
00091 
00092 protected:
00093   typedef multimap<char_type, state_type, 
00094                    nfa_mmap_key_compare<char_traits> > transition_container; 
00095   typedef vector<char> set_F;
00096   typedef nfa_mmap_state_data<state_type, char_traits, tag_type> state_data;
00097 
00098   // Copy construction for duplicate:
00099   state_type new_state(const state_data &x) {
00100     Q.push_back(new state_data(x));
00101     ++state_count_;
00102     trans_count_ += x.edges.size();
00103     return Q.size() - 1;
00104   }
00105 
00106   vector<state_data*> Q;
00107   set<state_type>     I;     // Initial states
00108   set_F               F;     // Final states
00109   unsigned long       state_count_, trans_count_;
00110 
00111 public:
00112   class edges_type
00113   {
00114     friend class NFA_mmap<_Sigma, _Tag>;
00115   protected:
00116     const transition_container *container;
00117     
00118   public:
00119     typedef typename transition_container::key_type        key_type;
00120     typedef typename transition_container::mapped_type       mapped_type;
00121     typedef typename transition_container::mapped_type       data_type;
00122     typedef typename transition_container::value_type      value_type;
00123     typedef typename transition_container::key_compare     key_compare;
00124     typedef typename transition_container::const_reference const_reference;
00125     typedef typename transition_container::size_type       size_type;
00126     typedef typename transition_container::difference_type difference_type;
00127     typedef typename transition_container::value_compare   value_compare;
00128 
00129     typedef typename transition_container::const_iterator         const_iterator;
00130     typedef typename transition_container::const_reverse_iterator const_reverse_iterator;
00131 
00132     // allocation/deallocation:
00133     
00134   protected:
00135     edges_type(const transition_container *c)
00136       : container(c) { }
00137 
00138   public:
00139     edges_type(const edges_type& x) : container(x.container) { }
00140     ~edges_type() { }
00141     
00142     // accessors:
00143     key_compare key_comp() const { return container->key_comp(); } 
00144     value_compare value_comp() const { return container->value_comp(); }
00145     const_iterator begin() const { return container->begin(); }
00146     const_iterator end() const { return container->end(); }
00147     const_reverse_iterator rbegin() const { return container->rbegin(); }
00148     const_reverse_iterator rend() const { return container->rend(); }
00149     bool empty() const { return container->empty(); }
00150     size_type size() const { return container->size(); }
00151     size_type max_size() const { return container->max_size(); }
00152     
00153     // map operations:
00154     const_iterator find(const key_type& x) const { return container->find(x); }
00155     size_type count(const key_type& x) const { return container->count(x); }
00156     const_iterator lower_bound(const key_type& x) const { return container->lower_bound(x); }
00157     const_iterator upper_bound(const key_type& x) const { return container->upper_bound(x); }
00158     pair<const_iterator, const_iterator> equal_range(const key_type& x) const {
00159       return container->equal_range(x);
00160     }
00161 
00162     // comparison:
00163     friend bool operator == (const edges_type& x, const edges_type& y) {
00164       return x.container == y.container || *x.container == *y.container;
00165     }
00166   };
00167 
00168   typedef skip_blanks_iterator<state_data>       const_iterator;
00169 
00170   // Backward compatibility:
00171   typedef edges_type Edges;
00172 
00173   static const state_type null_state = 0;
00174 
00175   set<state_type>& initial() { 
00176     return I; 
00177   }
00178 
00179   const set<state_type>& initial() const { 
00180     return I; 
00181   }
00182 
00183   set_F::reference final(state_type s) { 
00184     return F[s]; 
00185   }
00186 
00187   bool final(state_type s) const { 
00188     return F[s] != '\0'; 
00189   }
00190 
00191   state_type new_state() 
00192   {
00193     Q.push_back(new state_data);
00194     ++state_count_;
00195     F.push_back('\0');
00196     return Q.size() - 1;
00197   }
00198 
00199   template <class OutputIterator>
00200   OutputIterator new_state(unsigned long how_many, OutputIterator x)
00201   {
00202     for(; how_many > 0; --how_many)
00203       *x++ = new_state();
00204     return (x);
00205   }
00206 
00207   void del_state(state_type s) 
00208   { 
00209     trans_count_ -= Q[s]->edges.size();
00210     delete Q[s];
00211     --state_count_;
00212     Q[s] = NULL;
00213     I.erase(s);
00214   }
00215 
00216   void set_trans(state_type s, const char_type &l, state_type aim)
00217   {
00218     Q[s]->edges.insert(make_pair(l, aim));
00219     ++trans_count_;
00220   }
00221 
00222   void del_trans(state_type s, const char_type &l) {
00223     trans_count_ -= Q[s]->edges.erase(l);
00224   }
00225 
00226   void del_trans(state_type s, const char_type &l, state_type aim)
00227   {
00228     pair<typename multimap<char_type, state_type>::iterator, 
00229       typename multimap<char_type, state_type>::iterator>
00230       p = Q[s]->edges.equal_range(l);
00231     for(; p.first != p.second && (*p).second != aim; ++p.first);
00232     Q[s]->edges.erase(p.first);
00233     --trans_count_;
00234   }
00235 
00236   void change_trans(state_type s, const char_type &l, 
00237                     state_type former_aim, state_type new_aim)
00238   {
00239     transition_container &e = Q[s]->edges;
00240     typename transition_container::iterator p = e.find(l);
00241     for(; (*p).second != former_aim; ++p);
00242     (*p).second = new_aim;
00243   }
00244 
00245   void copy_state(state_type from, state_type to)
00246   {
00247     trans_count_ += Q[from]->edges.size() - Q[to]->edges.size();
00248     *Q[to] = *Q[from];
00249     F[to] = F[from];
00250   }
00251 
00252   template <class OutputIterator>
00253   OutputIterator delta1(state_type s, const char_type &l, 
00254                         OutputIterator x) const
00255   {
00256     return std::transform(Q[s]->edges.lower_bound(l), 
00257                           Q[s]->edges.upper_bound(l), 
00258                           x, select2nd<pair<char_type, state_type> >()); 
00259   }
00260 
00261   state_type duplicate_state(state_type q) {
00262     state_type s = new_state(*Q[q]);  // protected method for copy-construction
00263     F[s] = F[q];
00264     return s;
00265   }
00266 
00267   unsigned long state_count() const { 
00268     return state_count_;
00269   }
00270 
00271   unsigned long trans_count() const { 
00272     return trans_count_; 
00273   }
00274   
00275   Tag& tag(state_type s) { 
00276     return Q[s]->t; 
00277   }
00278 
00279   const Tag& tag(state_type s) const { 
00280     return Q[s]->t; 
00281   }
00282 
00283   edges_type delta2(state_type s) const { 
00284     return edges_type(&Q[s]->edges); 
00285   }
00286 
00287   const_iterator begin() const { 
00288     const_iterator x(&Q, 0);
00289     return ++x;
00290   }
00291 
00292   const_iterator end() const { 
00293     return const_iterator(&Q, Q.size());
00294   }
00295   
00296   NFA_mmap(unsigned long n = 0)
00297     : Q(1, (state_data*) NULL), I(), F(1, '\0'), state_count_(0), 
00298       trans_count_(0) { 
00299     Q.reserve(n + 1);
00300   }
00301 
00302   ~NFA_mmap()
00303   {
00304     const_iterator start, finish = end();
00305     for(start = begin(); start != finish; ++start)
00306       del_state(*start);
00307   }
00308 };
00309 
00310 template <typename CharTraits, typename Tag>
00311 const typename NFA_mmap<CharTraits, Tag>::state_type 
00312 NFA_mmap<CharTraits, Tag>::null_state;
00313 
00314 } // namespace astl
00315 
00316 #endif   // ASTL_NFA_MMAP_H
00317 
00318 
00319 
00320 
00321 
00322 
00323 
00324 

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