Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members

nfa.h

00001 /***************************************************************************
00002                           nfa.h  -  description
00003                              -------------------
00004     begin                : Wed Nov 26 2003
00005     copyright            : (C) 2003 by Jacques Gasselin de Richebourg
00006     email                : jacquesgasselin@hotmail.com
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU Lesser General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  *   This library is distributed in the hope that it will be useful,       *
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00019  *   Lesser General Public License for more details.                       *
00020  *                                                                         *
00021  *   You should have received a copy of the GNU Lesser General Public      *
00022  *   License along with this library; if not, write to the Free Software   *
00023  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *
00024  *                                                                         *
00025  ***************************************************************************/
00026 
00027 #ifndef NFA_H
00028 #define NFA_H
00029 
00030 #include <list>
00031 #include <map>
00032 #include <vector>
00033 #include <algorithm>
00034 #include <functional>
00035 
00040 void NFAunitTest(void);
00041   
00042 template <class InType>
00043 class FAState;
00044 
00045 template <class InType>
00046 class NFA;
00047 
00048 template <class InType>
00049 class FATraversalPointer
00050 {
00051    typedef FAState<InType> stateType;
00052 
00053    stateType* atState;
00054    bool dead;
00055    
00056    public:
00057 
00058 
00059    FATraversalPointer(stateType* beginState)
00060    :atState(beginState),dead(false) {};
00061 
00062    FATraversalPointer(const FATraversalPointer& _fa )
00063    :atState(_fa.atState),dead(_fa.dead) {};
00064 
00065    ~FATraversalPointer(){};
00066 
00067    bool operator ==( const FATraversalPointer& _fa )
00068    {
00069       if( atState == _fa.atState )
00070          return true;
00071       return false;
00072    }
00073    
00074    void traverse( const InType& in )
00075    {
00076       atState->traverse( *this, in );
00077    }
00078 
00079    bool isDead() { return dead; }
00080    
00081    void kill() { dead = true; }
00082 };
00083 
00084 template <class InType>
00085 class FAEdge
00086 {
00087    InType acceptedInput;
00088 
00089    typedef FAState<InType> stateType;
00090 
00091    stateType* to;
00092    
00093    public:
00094    
00095    FAEdge(const InType& _in, stateType* const _to = NULL)
00096    :acceptedInput(_in), to(_to) {}
00097    
00098    ~FAEdge(){};
00099 
00100    void setAcceptedInput( const InType& in )
00101    {
00102       acceptedInput = in;
00103    }
00104 
00105    bool canTraverseAlong( const InType& in )
00106    {
00107       if(acceptedInput == in)
00108          return true;
00109       else
00110          return false;
00111    }
00112 
00113    void connectTo(stateType* const _to)
00114    { to = _to; }
00115    
00116    stateType* getDesination() { return to; }
00117          
00118 };
00119 
00120 template <class InType>
00121 class FAState
00122 {
00123    typedef std::vector< FAEdge<InType> * > EdgeVectorType;
00124    typedef FATraversalPointer<InType> TraversalPtr;
00125 
00126 
00127    EdgeVectorType edgeVector;
00128 
00129    public:                  
00130    
00131    FAState(NFA<InType>* const pa, bool _goal = false )
00132    :parentAutomata( pa ),goalState(_goal) { edgeVector.clear(); }
00133    
00134    virtual ~FAState()
00135    {
00136       typename EdgeVectorType::iterator li = edgeVector.begin();
00137       typename EdgeVectorType::iterator end = edgeVector.end();
00138 
00139       while( li != end )
00140       {
00141          delete (*li);
00142          ++li;
00143       }
00144       
00145       edgeVector.clear();
00146    };
00147 
00148    virtual void traverse(  TraversalPtr& ptr, const InType& in )
00149    {
00150       typename EdgeVectorType::iterator li = edgeVector.begin();
00151       typename EdgeVectorType::iterator end = edgeVector.end();
00152 
00153       bool accepted = false;
00154       
00155       while( li != end )
00156       {
00157          if( (*li)->canTraverseAlong( in ) )  //generate offspring
00158          {
00159             parentAutomata->addTraversalPtr( TraversalPtr( (*li)->getDesination() ) );
00160             accepted = true;
00161          }
00162          ++li;
00163       };
00164 
00165       // the pointer goes dead
00166       if( !accepted )
00167       {
00168          if(goalState)
00169          { // dead pointers here satisfy the goal
00170             parentAutomata->setGoal();
00171          }
00172       }
00173 
00174       ptr.kill();
00175    }
00176 
00177    FAEdge<InType>* addEdge( const InType& _in, int _stateIndex )
00178    {
00179       FAEdge<InType>* temp = new FAEdge<InType>( _in, parentAutomata->getState(_stateIndex) ); 
00180       edgeVector.push_back( temp );
00181       return temp;
00182    }
00183 
00184    FAEdge<InType>* addEdge( const InType& _in )
00185    {
00186       FAEdge<InType>* temp = new FAEdge<InType>( _in, NULL );
00187       edgeVector.push_back( temp );
00188       return temp;
00189    }
00190 
00191    FAEdge<InType>* const getEdge(unsigned index )
00192    {
00193       return edgeVector[index];
00194    }
00195 
00196    FAEdge<InType>* const operator [](unsigned index)
00197    {
00198       return edgeVector[index];
00199    }
00200 
00201    void setGoalState( void )
00202    { goalState = true; }
00203    
00204    private:
00205 
00206    NFA<InType>* parentAutomata;
00207    bool goalState;
00208 
00209 
00210 };
00211 
00212 template <class InType>
00213 class NFA
00214 {
00215    typedef FATraversalPointer<InType> TraversalPtr;
00216    typedef std::list<TraversalPtr > TraversalListType;
00217    typedef FAState<InType> StateType;
00218    typedef std::vector<StateType* > StateListType;
00219 
00220    bool goalReached;
00221    int token;
00222    TraversalListType travPtrList;
00223    TraversalListType waitingTravPtrList;
00224    
00225    public:
00226 
00227    NFA(int t = 0)
00228    :goalReached(false),token(t)
00229    { }
00230    
00231    virtual ~NFA()
00232    {
00233       typename StateListType::iterator li = stateList.begin();
00234       typename StateListType::iterator end = stateList.end();
00235 
00236       while( li != end )
00237       {
00238          delete (*li);
00239          ++li;
00240       };
00241 
00242       stateList.clear();
00243       travPtrList.clear();
00244    }
00245 
00246    virtual const int getToken( void )
00247    {
00248       unsetGoal();
00249       return token;
00250    }
00251 
00252    virtual void setToken( int _t )
00253    {
00254       token = _t;
00255    }
00256 
00257    virtual bool scanInput(const InType& t)
00258    {
00259       travPtrList.push_back( TraversalPtr( *(stateList.begin()) ) );
00260       //add a new empty pointer each round
00261       
00262       typename TraversalListType::iterator li = waitingTravPtrList.begin();
00263       typename TraversalListType::iterator end = waitingTravPtrList.end();
00264 
00265       while( li != end )
00266       {
00267          travPtrList.push_back( *li );
00268          ++li;
00269       };
00270       //copy over the waiting pointers
00271       waitingTravPtrList.clear();
00272 
00273       li = travPtrList.begin();
00274       end = travPtrList.end();
00275 
00276       while( li != end )
00277       {
00278          li->traverse( t );
00279          ++li;
00280       };
00281       //traverse all living pointers
00282 
00283       li = travPtrList.begin();
00284       end = travPtrList.end();
00285 
00286       while( li != end )
00287       {
00288          if( !li->isDead() )
00289             waitingTravPtrList.push_back( *li );
00290          ++li;
00291       };
00292       //make all living pointers wait, and kill the rest
00293       
00294       travPtrList.clear();
00295       
00296       return goalReached;
00297    }
00298 
00299    virtual void addTraversalPtr( const TraversalPtr& ptr )
00300    {
00301       waitingTravPtrList.push_back( ptr );
00302    }
00303    
00304    virtual void addState( void )
00305    {
00306       stateList.push_back( new StateType(this) );
00307    }
00308 
00309    virtual StateType* const getState( unsigned index )
00310    {
00311       while( index >= stateList.size() )
00312          addState();
00313       
00314       return stateList[index];
00315    }
00316 
00317    StateType* const operator []( unsigned index)
00318    {
00319       while( index >= stateList.size() )
00320          addState();
00321 
00322       return stateList[index];
00323    }
00324    
00325    virtual void setGoal( void )
00326    { goalReached = true; }
00327 
00328    protected:
00329 
00330 
00331    virtual void unsetGoal( void )
00332    { goalReached = false; }
00333 
00334 
00335    private:
00336 
00337    StateListType stateList;
00338    
00339 };
00340        
00341 
00342 #endif

Generated on Wed Feb 4 23:11:34 2004 by doxygen 1.3.3