debug.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_DEBUG_H
00023 #define ASTL_DEBUG_H
00024 
00025 #include <astl.h>
00026 #include <iostream>
00027 #include <utility>  // pair<>
00028 
00029 using namespace std;
00030 
00031 namespace astl {
00032 
00033 // A plain cursor with default behavior checking its state before any
00034 // processing:
00035 template <class DFA>
00036 class cursor_debug : public cursor_concept
00037 {
00038 public:
00039   typedef cursor_debug              self;
00040   typedef typename DFA::state_type  state_type;
00041   typedef typename DFA::tag_type    tag_type;
00042   typedef typename DFA::char_type   char_type;
00043   typedef typename DFA::char_traits char_traits;
00044 
00045   // Backward compatibility typedefs:
00046   typedef state_type  State;
00047   typedef tag_type    Tag;
00048   typedef char_type   Alphabet;
00049   typedef char_traits Sigma;
00050 
00051 protected:
00052   const DFA *dfa;
00053   state_type q;
00054   bool singular;
00055   ostream &out;
00056 
00057 public:
00058   cursor_debug(ostream &o = cerr)
00059     : dfa(NULL), singular(true), out(o) 
00060   { }
00061 
00062   cursor_debug(const DFA &a, ostream &o = cerr)
00063     : dfa(&a), singular(true), out(o) 
00064   { }
00065 
00066   cursor_debug(const DFA &a, state_type p, ostream &o = cerr)
00067     : dfa(&a), q(p), out(o)
00068   {
00069     if (q == dfa->null_state) {
00070       out << "cursor::cursor(DFA, state_type) : WARNING" << endl;
00071       out << "\t cursor set on the sink state" << endl;
00072     }
00073   }
00074 
00075   state_type sink_state() const {
00076     if (singular) {
00077       out << "cursor::sink_state(): CRITICAL" << endl;
00078       out << "\t accessing sink state through a singular cursor" << endl;
00079     }
00080     return dfa->null_state;
00081   }
00082 
00083   state_type src() const {
00084     if (singular) {
00085       out << "cursor::src(): CRITICAL" << endl;
00086       out << "\t trying to access state through a singular cursor" << endl;
00087     }
00088     return q;
00089   }
00090 
00091   self& operator= (state_type p) { 
00092     q = p;
00093     if (q == dfa->null_state) {
00094       out << "cursor::operator=(state_type) : WARNING" << endl;
00095       out << "\t assigning sink state to the cursor" << endl;
00096     }
00097     singular = false;
00098     return *this;
00099   }
00100 
00101   self& operator=(const self &x) {  
00102     if (this == &x) {
00103       out << "cursor::operator=(cursor &x) : WARNING" << endl;
00104       out << "\t assigning cursor to itself (this == &x)" << endl;
00105     }
00106     q = x.q;
00107     dfa = x.dfa;
00108     singular = x.singular;
00109     if (singular) {
00110       out << "cursor::operator=(cursor &x): CRITICAL" << endl;
00111       out << "\t x has a singular value" << endl;
00112     }
00113     return *this;
00114   }
00115 
00116   bool operator==(const self &x) const {
00117     if (this == &x) {
00118       out << "cursor::operator==(cursor &x) : WARNING" << endl;
00119       out << "\t comparing cursor to itself (this == &x)" << endl;
00120     }
00121     if (singular) {
00122       out << "cursor::operator==(cursor &x): CRITICAL" << endl;
00123       out << "\t comparing a singular cursor" << endl;
00124     }
00125     return q == x.q;
00126   }
00127 
00128   bool sink() const {  
00129     if (singular) {
00130       out << "cursor::sink(): CRITICAL" << endl;
00131       out << "\t testing a singular cursor" << endl;
00132     }
00133     return q == dfa->null_state;
00134   }
00135 
00136   bool forward(const char_type &letter) {  
00137     if (singular) {
00138       out << "cursor::forward(letter): CRITICAL" << endl;
00139       out << "\t trying to move along a transition through" 
00140         "a singular cursor" << endl;
00141     }
00142     else
00143       if (q == dfa->null_state) {
00144         out << "cursor::forward(letter): CRITICAL" << endl;
00145         out << "\t source state is the sink state" << endl;
00146       }
00147     q = dfa->delta1(q, letter);
00148     return q != dfa->null_state;
00149   }
00150 
00151   bool src_final() const {  
00152     if (singular) {
00153       out << "cursor::src_final(): CRITICAL" << endl;
00154       out << "\t trying to access source state of a singular cursor" << endl;
00155     }
00156     else
00157       if (q == dfa->null_state) {
00158         out << "cursor::src_final(): CRITICAL" << endl;
00159         out << "\t trying to access sink state" << endl;
00160       }
00161     return dfa->final(q);
00162   }
00163 
00164   const tag_type& src_tag() const  {   
00165     if (singular) {
00166       out << "cursor::src_tag(): CRITICAL" << endl;
00167       out << "\t testing a singular cursor" << endl;
00168     }
00169     else
00170       if (q == dfa->null_state) {
00171         out << "cursor::src_tag(): CRITICAL" << endl;
00172         out << "\t trying to access tag of sink state" << endl;
00173       }
00174     return dfa->tag(q);
00175   }
00176 
00177   bool exists(const char_type &letter) const {  // transition exists ?
00178     if (singular) {
00179       out << "cursor::exists(): CRITICAL" << endl;
00180       out << "\t testing for a transition through a singular cursor" << endl;
00181     }
00182     else
00183       if (q == dfa->null_state) {  
00184         out << "cursor::exists(): CRITICAL" << endl;
00185         out << "\t testing for an outgoing transition of sink state" << endl;
00186       }
00187     return dfa->delta1(q, letter) != dfa->null_state;
00188   }
00189 };
00190 
00191 // A forward cursor with default behavior checking its state before
00192 // any processing:
00193 template <class DFA>
00194 class forward_cursor_debug : public forward_cursor_concept
00195 {
00196 public:
00197   typedef forward_cursor_debug self;
00198   typedef typename DFA::state_type  state_type;
00199   typedef typename DFA::tag_type    tag_type;
00200   typedef typename DFA::char_type   char_type;
00201   typedef typename DFA::char_traits char_traits;
00202 
00203   // Backward compatibility typedefs:
00204   typedef state_type  State;
00205   typedef tag_type    Tag;
00206   typedef char_type   Alphabet;
00207   typedef char_traits Sigma;
00208 
00209 protected:
00210   typedef typename DFA::edges_type::const_iterator edges_iterator;
00211   const DFA *dfa;
00212   state_type q;
00213   edges_iterator transition;
00214   bool dereferenceable, singular;  // singular: the only allowed
00215                                    // operation is assignment 
00216   // dereferenceable: letter and aim of current transition
00217   //                  are accessible
00218   ostream &out;
00219 
00220 public:
00221   forward_cursor_debug(const DFA &a, state_type p, 
00222                        const char_type& Letter, ostream &o = cerr) 
00223     : dfa(&a), q(p), dereferenceable(false), singular(false), out(o)
00224   { 
00225     if (q == dfa->null_state) 
00226       out << "forward_cursor::forward_cursor(DFA, state_type, letter): warning" << endl
00227            << "\t cursor initialized with null state" << endl;
00228     else
00229       if ((transition = dfa->delta2(q).find(Letter)) == dfa->delta2(q).end()) {
00230         out << "forward_cursor::forward_cursor(DFA, state_type, letter): warning" << endl;
00231         out << "\t cursor set on a sink transition" << endl; 
00232       }
00233       else
00234         dereferenceable = true;
00235   }
00236   
00237   forward_cursor_debug(const DFA &a, state_type p, 
00238                        edges_iterator t, ostream &o = cerr)
00239     : dfa(&a), q(p), transition(t), dereferenceable(false), singular(false), out(o)
00240   { 
00241     if (q == dfa->null_state) {
00242       out << "forward_cursor::forward_cursor(DFA, state_type, edges_iterator):";
00243       out << " warning" << endl << "\t cursor initialized with null state" << endl;
00244     } 
00245     else 
00246       dereferenceable = t != dfa->delta2(q).end();
00247   }
00248   
00249   forward_cursor_debug(const DFA &a, state_type p, ostream &o = cerr)
00250     : dfa(&a), q(p), dereferenceable(false), singular(false), out(o)
00251   { 
00252     if (q == dfa->null_state) {
00253       out << "forward_cursor::forward_cursor(DFA, state_type): warning" << endl;
00254       out << "\t cursor initialized with null state" << endl;
00255     } 
00256   }
00257 
00258   forward_cursor_debug(const DFA &a, ostream &o = cerr)
00259     : dfa(&a), q(a.initial()), dereferenceable(false), singular(true), out(o)
00260   { 
00261     if (q == dfa->null_state) {
00262       out << "forward_cursor::forward_cursor(DFA): warning" << endl;
00263       out << "\t cursor initialized with initial state which is null" << endl;
00264     } 
00265   }
00266 
00267   forward_cursor_debug(ostream &o = cerr)
00268     : dfa(NULL), dereferenceable(false), singular(true), out(o)
00269   { }
00270 
00271   self& operator= (state_type p) { 
00272     //    out << "\t assigning" << endl;
00273     q = p;
00274     dereferenceable = false;
00275     if (q == dfa->null_state) {
00276       out << "forward_cursor::operator= (state_type): warning" << endl;
00277       out << "\t assigning null state" << endl;
00278     }
00279     singular = false;
00280     return *this;
00281   }
00282 
00283   self& operator= (const self &x) { 
00284     // out << "\t assigning self " << endl;
00285     if (this == &x) {
00286       out << "forward_cursor::operator= (forward_cursor x): warning" << endl;
00287       out << "\t assigning cursor to itself (this == &x)" << endl;
00288     }
00289     q = x.q;
00290     transition = x.transition;
00291     dereferenceable = x.dereferenceable;
00292     singular = x.singular;
00293     dfa = x.dfa;
00294     if (singular) {
00295       out << "forward_cursor::operator= (forward_cursor x): warning" << endl;
00296       out << "\t x has a singular value" << endl;
00297     }
00298     if (dfa == NULL) {
00299       out << "forward_cursor::operator= (forward_cursor x): WARNING" << endl;
00300       out << "\t assigning a non-initialized cursor x (dfa == NULL)" << endl;
00301     }
00302       
00303     return *this;
00304   }
00305 
00306   bool operator== (const self &x) const {
00307     if (this == &x) {
00308       out << "forward_cursor::operator== : warning" << endl;
00309       out << "\t comparing cursor with itself" << endl;
00310     }
00311     return (q == x.q && transition == x.transition);
00312   }
00313 
00314   char_type letter() const {
00315     if (singular) {
00316       out << "forward_cursor::letter() : CRITICAL" << endl;
00317       out << "\t trying to access transition through a singular cursor" << endl;
00318     } 
00319     else
00320       if (!dereferenceable) {
00321         out << "forward_cursor::letter() : CRITICAL" << endl;
00322         out << "\t trying to access transition through a non dereferenceable cursor" << endl;
00323         out << "\t state = " << q << endl;
00324       }
00325     return (*transition).first;
00326   }
00327 
00328   bool sink() const {
00329     if (singular) {
00330       out << "forward_cursor::sink(): CRITICAL" << endl;
00331       out << "\t testing for sink state on a singular cursor" << endl;
00332     } 
00333     return q == dfa->null_state;
00334   }
00335 
00336   state_type sink_state() const { 
00337     // out << "\t sink_state(  " << endl;
00338     if (singular) {
00339       out << "forward_cursor::sink_state(): CRITICAL" << endl;
00340       out << "\t requesting the sink state value from a singular cursor" << endl;
00341     } 
00342     return dfa->null_state;
00343   }
00344 
00345   // Obsolet:
00346   void to_sink() {
00347     if (singular) {
00348       out << "forward_cursor::to_sink(): CRITICAL" << endl;
00349       out << "\t moving a singular cursor to the sink state" << endl;
00350     } 
00351     if (dfa == NULL) {
00352       out << "forward_cursor::to_sink() : CRITICAL" << endl;
00353       out << "\t trying to move to the sink state with a non-initialized cursor (dfa == NULL)" << endl;
00354     } 
00355     q = dfa->null_state;
00356   }
00357     
00358 
00359   bool first() {
00360     if (singular) {
00361       out << "forward_cursor::first() : CRITICAL" << endl;
00362       out << "\t seeking first outgoing transition of a singular cursor" << endl;
00363     } 
00364     else
00365       if (q == dfa->null_state) {
00366         out << "forward_cursor::first() : CRITICAL" << endl;
00367         out << "\t trying to access first transition of sink source state" << endl;
00368       }
00369     return dereferenceable = (transition = dfa->delta2(q).begin()) != dfa->delta2(q).end();
00370   }
00371   
00372   bool next() { 
00373     if (singular) {
00374       out << "forward_cursor::next() : CRITICAL" << endl;
00375       out << "\t seeking next transition of a singular cursor" << endl;
00376     } 
00377     else
00378       if (q == dfa->null_state) {
00379         out << "forward_cursor::next() : CRITICAL" << endl;
00380         out << "\t seeking next transition of sink source state" << endl;
00381       }
00382       else
00383         if (!dereferenceable) {
00384           out << "forward_cursor::next(): CRITICAL" << endl;
00385           out << "\t seeking next transition of a non dereferenceable cursor" << endl;
00386         }
00387     return dereferenceable = (++transition != dfa->delta2(q).end());
00388   }
00389 
00390   void forward() {
00391     if (singular) {
00392       out << "forward_cursor::forward() : CRITICAL" << endl;
00393       out << "\t trying to move along transition of a singular cursor" << endl;
00394     }
00395     else
00396       if (q == dfa->null_state) {
00397         out << "forward_cursor::forward() : CRITICAL" << endl;
00398         out << "\t trying to move along transition of sink source state" << endl;
00399       }
00400       else
00401         if (!dereferenceable) {
00402           out << "forward_cursor::forward() : CRITICAL" << endl;
00403           out << "\t trying to move along transition of a non dereferenceable cursor" << endl;
00404         }
00405     q = (*transition).second;
00406     dereferenceable = false;
00407   }
00408 
00409   bool find(const char_type &letter)  {
00410     if (singular) {
00411       out << "forward_cursor::find() : CRITICAL" << endl;
00412       out << "\t trying to find an outgoing transition through a singular cursor" << endl;
00413     }
00414     else
00415       if (q == dfa->null_state) {
00416         out << "forward_cursor::find() : CRITICAL" << endl;
00417         out << "\t trying to find an outgoing transition of sink source state" << endl;
00418       }
00419     edges_iterator tmp = dfa->delta2(q).find(letter);
00420     if (tmp != dfa->delta2(q).end()) {
00421       transition = tmp;
00422       dereferenceable = true; // out << " Found " << endl ;
00423       return true;
00424     }
00425     //    out << "not Found " << endl ;
00426     return false;
00427   }
00428 
00429   bool forward(const char_type &letter) {
00430     if (singular) {
00431       out << "forward_cursor::forward(letter) : CRITICAL" << endl;
00432       out << "\t trying to move along transition through a singular cursor" << endl;
00433     }
00434     else
00435       if (q == dfa->null_state) {
00436         out << "forward_cursor::forward(letter) : CRITICAL" << endl;
00437         out << "\t trying to move along outgoing transition of sink state" << endl;
00438       }
00439     dereferenceable = false;
00440     q = dfa->delta1(q, letter);
00441     return q != dfa->null_state;
00442   }
00443 
00444   state_type src() const {
00445     if (singular) {
00446       out << "forward_cursor::src(): CRITICAL" << endl;
00447       out << "\t trying to access source state of a singular cursor" << endl;
00448     }
00449     return q;
00450   }
00451 
00452   state_type aim() const {
00453     if (singular) {
00454       out << "forward_cursor::aim() : CRITICAL" << endl;
00455       out << "\t trying to access aim state of a singular cursor" << endl;
00456     }
00457     else
00458       if (!dereferenceable) {
00459         out << "forward_cursor::aim() : CRITICAL" << endl;
00460         out << "\t trying to access aim state of a non dereferenceable cursor" << endl;
00461       }
00462     return (*transition).second;
00463   }
00464 
00465   bool src_final() const {
00466     if (singular) {
00467       out << "forward_cursor::src_final(): CRITICAL" << endl;
00468       out << "\t trying to access source state of a singular cursor" << endl;
00469     }
00470     else
00471       if (q == dfa->null_state) {
00472         out << "forward_cursor::src_final(): CRITICAL" << endl;
00473         out << "\t trying to access sink state" << endl;
00474       }
00475     return dfa->final(q);
00476   }
00477 
00478   bool aim_final() const {
00479     if (singular) {
00480       out << "forward_cursor::aim_final() : CRITICAL" << endl;
00481       out << "\t trying to access aim state of a singular cursor" << endl;
00482     }
00483     else
00484       if (!dereferenceable) {
00485         out << "forward_cursor::aim_final() : CRITICAL" << endl;
00486         out << "\t trying to access aim state of a non dereferenceable cursor" << endl;
00487       }
00488     return dfa->final((*transition).second);
00489   }
00490 
00491   bool exists(const char_type &letter) const {  // transition exists ?
00492     //    out << "\t exist " << endl;
00493     if (singular) {
00494       out << "forward_cursor::exist() : CRITICAL" << endl;
00495       out << "\t testing for a transition through a singular cursor" << endl;
00496     }
00497     else if (!dereferenceable) {
00498       out << "forward_cursor::exist() : CRITICAL" << endl;
00499       out << "\t testing for a transition through a non dereferenceable cursor" << endl;
00500     }
00501     else
00502       if (q == dfa->null_state) {  
00503         out << "forward_cursor::exist() : CRITICAL" << endl;
00504         out << "\t testing for a transition from sink state" << endl;
00505       }
00506     return dfa->delta1(q, letter) != dfa->null_state;
00507   }
00508 
00509   const tag_type& src_tag() const  {
00510     if (singular) {
00511       out << "forward_cursor::src_tag() : CRITICAL" << endl;
00512       out << "\t trying to access source tag of a singular cursor" << endl;
00513     }
00514     else
00515       if (q == dfa->null_state) {
00516         out << "forward_cursor::src_tag(): CRITICAL" << endl;
00517         out << "\t trying to access tag of sink state" << endl;
00518       }
00519     return dfa->tag(q);
00520   }
00521 
00522   const tag_type& aim_tag() const {
00523     if (singular) {
00524       out << "forward_cursor::aim_tag() : CRITICAL" << endl;
00525       out << "\t trying to access aim tag of a singular cursor" << endl;
00526     }
00527     else
00528       if (!dereferenceable) {
00529         out << "forward_cursor::aim_tag() : CRITICAL" << endl;
00530         out << "\t trying to access aim tag of a non dereferenceable cursor";
00531       }
00532     return dfa->tag((*transition).second);
00533   }
00534 
00535   // Not a standard requirement:
00536   friend ostream& operator << (ostream &out, const self &x) {
00537     out << x.q << " , '";
00538     if (x.singular) out << "singular'";
00539     else
00540       if (!x.dereferenceable) {
00541         if (x.transition == x.dfa->delta2(x.q).end()) out << "end of range'";
00542         else
00543           out << "not dereferenceable'";
00544       }
00545       else
00546         out << (*(x.transition)).first << "', " << (*(x.transition)).second;
00547     return out;
00548   }
00549 
00550   // Not a standard requirement:
00551   bool operator < (const self &x) const {   
00552     // STL containers need operator < on
00553     // their value_type (to define < on themselves)
00554     if (singular) 
00555       out << "forward_cursor::operator< (forward_cursor) : caution" << endl
00556            << "\t comparing singular left cursor with"
00557            << (x.singular ? " singular " : " ") << "right cursor" << endl; 
00558     else
00559       if (x.singular)
00560         out << "forward_cursor::operator< (forward_cursor) : caution" << endl
00561              << "\t comparing left cursor with singular right cursor" << endl; 
00562     return q < x.q || (q == x.q && transition < x.transition);
00563   }
00564 };
00565 
00566 // Helper functions:
00567 // Build a debug plain cursor from a DFA:
00568 template <class DFA>
00569 cursor_debug<DFA> debugplainc(const DFA &a, ostream &out = cerr) {
00570   return cursor_debug<DFA>(a, a.initial(), out);
00571 }
00572 
00573 // Build a debug forward cursor from a DFA:
00574 template <class DFA>
00575 forward_cursor_debug<DFA> debugc(const DFA &a, ostream &out = cerr) {
00576   return forward_cursor_debug<DFA>(a, a.initial(), out);
00577 }
00578 
00579 template <class Cursor>
00580 class cursor_trace : public cursor_concept
00581 {
00582 public:
00583   typedef cursor_trace              self;
00584   typedef typename Cursor::state_type  state_type;
00585   typedef typename Cursor::tag_type    tag_type;
00586   typedef typename Cursor::char_type   char_type;
00587   typedef typename Cursor::char_traits char_traits;
00588   static int id;
00589 
00590   // Backward compatibility typedefs:
00591   typedef state_type  State;
00592   typedef tag_type    Tag;
00593   typedef char_type   Alphabet;
00594   typedef char_traits Sigma;
00595 
00596 protected:
00597   Cursor c;
00598   int ID;
00599   ostream &out;
00600 
00601 public:
00602   cursor_trace(ostream &o = cerr)
00603     : c(), ID(++id), out(o) { 
00604     out << "cursor[" << ID << "]::cursor()" << endl;
00605   }
00606 
00607   cursor_trace(const Cursor &x, ostream &o = cerr)
00608     : c(x), ID(++id), out(o) {
00609     out << "cursor[" << ID << "]::cursor(Cursor " << &x << ")" << endl;
00610   }
00611 
00612   cursor_trace(const self &x) 
00613     : c(x.c), ID(x.ID), out(x.out) {
00614     out << "cursor[" << ID << "]::cursor(self)" << endl;
00615   }
00616 
00617   ~cursor_trace() {
00618     out << "cursor[" << ID << "]::~cursor()" << endl;
00619   }
00620 
00621   state_type src() const {
00622     out << "cursor[" << ID << "]::src() == " << c.src() << endl;
00623     return c.src();
00624   }
00625 
00626   state_type sink_state() const {
00627     out << "cursor[" << ID << "]::sink_state() == " << c.sink_state() << endl;
00628     return c.sink_state();
00629   }
00630 
00631   self& operator= (state_type p) {
00632     out << "cursor[" << ID << "]::operator=(state_type " << p << ")" << endl;
00633     c = p;
00634     return *this;
00635   }
00636 
00637   self& operator= (const self &x) {
00638     out << "cursor[" << ID << "]::operator=(self [" << x.ID << "])" << endl;
00639     c = x.c;
00640     return *this;
00641   }
00642 
00643   bool operator== (const self &x) const {
00644     out << "cursor[" << ID << "]::operator==(self [" << x.ID << "]) == " << (c == x.c) << endl;
00645     return c == x.c;
00646   }
00647 
00648   bool sink() const {
00649     out << "cursor[" << ID << "]::sink() == " << c.sink() << endl;
00650     return c.sink();
00651   }
00652 
00653   bool forward(const char_type &letter) {
00654     out << "cursor[" << ID << "]::forward('" << letter << "') == ";
00655     out << c.forward(letter) << endl;
00656     return !c.sink();
00657   }
00658 
00659   bool src_final() const {
00660     out << "cursor[" << ID << "]::src_final() == " << c.src_final() << endl;
00661     return c.src_final();
00662   }
00663 
00664   const tag_type& src_tag() const  {
00665     out << "cursor[" << ID << "]::src_tag()" << endl;
00666     return c.src_tag();
00667   }
00668 
00669   bool exists(const char_type &letter) const {      // transition exists ?
00670     out << "cursor[" << ID << "]::exists(int " << letter << ") == " << c.exists(letter) << endl;
00671     return c.exists(letter);
00672   }
00673 };
00674 
00675 template <class Cursor> int cursor_trace<Cursor>::id = 0;
00676 
00677 template <class ForwardCursor>
00678 class forward_cursor_trace : public forward_cursor_concept
00679 {
00680 public:
00681   typedef forward_cursor_trace             self;
00682   typedef typename ForwardCursor::state_type  state_type;
00683   typedef typename ForwardCursor::tag_type    tag_type;
00684   typedef typename ForwardCursor::char_type   char_type;
00685   typedef typename ForwardCursor::char_traits char_traits;
00686 
00687   // Backward compatibility typedefs:
00688   typedef state_type  State;
00689   typedef tag_type    Tag;
00690   typedef char_type   Alphabet;
00691   typedef char_traits Sigma;
00692 
00693 protected:
00694   ForwardCursor c;
00695   static int id;
00696   int ID;
00697   ostream &out;
00698 
00699 public:
00700   forward_cursor_trace(const ForwardCursor &x, ostream &o = cerr)
00701     : c(x), ID(++id), out(o) { 
00702     out << "fcursor[" << ID << "]::fcursor(forward_cursor " << &x << ")" << endl;
00703   }
00704   
00705   forward_cursor_trace(ostream &o = cerr)
00706     : c(), ID(++id), out(o) { 
00707     out << "fcursor[" << ID << "]::fcursor()";
00708   }
00709 
00710   const ForwardCursor& cursor() const { return c; }
00711 
00712   forward_cursor_trace(const self &x) 
00713     : c(x.c), ID(++id), out(x.out) { 
00714     out << "fcursor[" << ID << "](self[" << x.ID << "])" << endl;
00715   }
00716 
00717   ~forward_cursor_trace() {
00718     out << "fcursor[" << ID << "]::~fcursor()" << endl;
00719   }
00720   
00721   self& operator= (state_type p) {
00722     out << "fcursor[" << ID << "]::operator=(state_type " << p << ")" << endl;
00723     c = p;
00724     return *this;
00725   }
00726 
00727   self& operator= (const self &x) {
00728     out << "fcursor[" << ID << "]::operator=(self [" << x.ID << "])" << endl;
00729     c = x.c;
00730     return *this;
00731   }
00732 
00733   bool operator== (const self &x) const {
00734     out << "fcursor[" << ID << "]::operator==(self [" << x.ID << "]) == " << (c == x.c) << endl;
00735     return (c == x.c);
00736   }
00737 
00738   char_type letter() const {
00739     out << "fcursor[" << ID << "]::letter() == '" << c.letter() << "'" << endl;
00740     return c.letter();
00741   }
00742 
00743   bool first() {
00744     out << "fcursor[" << ID << "]::first() == ";
00745     if (c.first())
00746       out << "(" << c.src() << ", '" << c.letter() << "', " << c.aim() << ")" << endl;
00747     else
00748       out << "0" << endl;
00749     return c.first();
00750   }
00751   
00752   bool next() {
00753     bool r = c.next();
00754     out << "fcursor[" << ID << "]::next() == ";
00755     if (r)
00756        out << "(" << c.src() << ", '" << c.letter() << "', " << c.aim() << ")" << endl;
00757     else
00758       out << "0" << endl;     
00759     return r;
00760   }
00761 
00762   bool forward(const char_type &letter) {
00763     out << "fcursor[" << ID << "]::forward('" << letter << "') == ";
00764     if (c.forward(letter))
00765       out << c.src() << endl;
00766     else {
00767       out << "0 && sink() == " << c.sink() << endl;
00768     }
00769     return !c.sink();
00770   }
00771 
00772   void forward() {
00773     c.forward();
00774     out << "fcursor[" << ID << "]::forward() == " << c.src() << endl;
00775   }
00776 
00777   bool find(const char_type &letter)  {
00778     out << "fcursor[" << ID << "]::find('" << letter << "') == ";
00779     if (c.find(letter))
00780       out << "(" << c.src() << ", '" << c.letter() << "', " << c.aim() << ")" << endl;
00781     else
00782       out << "0" << endl;     
00783     return c.find(letter);
00784   }
00785 
00786   state_type src() const {
00787     out << "fcursor[" << ID << "]::src() == " << c.src() << endl;
00788     return c.src();
00789   }
00790 
00791   bool src_final() const {
00792     out << "fcursor[" << ID << "]::src_final() == " << c.src_final() << endl;
00793     return c.src_final();
00794   }
00795 
00796   state_type aim() const {
00797 
00798     out << "fcursor[" << ID << "]::aim() == " << c.aim() << endl;
00799     return c.aim();
00800   }
00801 
00802   bool aim_final() const {
00803     out << "fcursor[" << ID << "]::aim_final() == " << c.aim_final() << endl;
00804     return c.aim_final();
00805   }
00806 
00807   tag_type aim_tag() const {
00808     out << "fcursor[" << ID << "]::aim_tag() == " << c.aim_tag() << endl;
00809     return c.aim_tag();
00810   }
00811 
00812   tag_type src_tag() const {
00813     out << "fcursor[" << ID << "]::src_tag() == " << c.src_tag() << endl;
00814     return c.src_tag();
00815   }
00816 
00817   bool sink() const {
00818     out << "fcursor[" << ID << "]::sink() == " << c.sink() << endl;
00819     return c.sink();
00820   }
00821 
00822   state_type sink_state() const {
00823     out << "fcursor[" << ID << "]::sink_state() == " << c.sink_state() << endl;
00824     return c.sink_state();
00825   }
00826 
00827   bool exists(const char_type &letter) const {      // transition exists ?
00828     out << "fcursor[" << ID << "]::exists(" << letter << ") == " << c.exists(letter) << endl;
00829     return c.exists(letter);
00830   }
00831 };
00832 
00833 template <class ForwardCursor> int forward_cursor_trace<ForwardCursor>::id = 0;
00834 
00835 template <class ForwardCursor>
00836 forward_cursor_trace<ForwardCursor> 
00837 tracec(const ForwardCursor &x, ostream &out = cerr) {
00838   return forward_cursor_trace<ForwardCursor>(x, out);
00839 }
00840 
00841 } // namespace astl
00842 
00843 #endif // ASTL_CURSOR_DEBUG

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