Vaucanson 1.4
dump_visitor.hxx
00001 // dump_visitor.hxx: this file is part of the Vaucanson project.
00002 //
00003 // Vaucanson, a generic library for finite state machines.
00004 //
00005 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2010 The Vaucanson Group.
00006 //
00007 // This program is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2
00010 // of the License, or (at your option) any later version.
00011 //
00012 // The complete GNU General Public Licence Notice can be found as the
00013 // `COPYING' file in the root directory.
00014 //
00015 // The Vaucanson Group consists of people listed in the `AUTHORS' file.
00016 //
00017 #ifndef VCSN_ALGEBRA_IMPLEMENTATION_SERIES_RAT_DUMP_VISITOR_HXX
00018 # define VCSN_ALGEBRA_IMPLEMENTATION_SERIES_RAT_DUMP_VISITOR_HXX
00019 
00020 # include <vaucanson/algebra/concept/letter.hh>
00021 # include <vaucanson/algebra/implementation/series/rat/dump_visitor.hh>
00022 # include <vaucanson/algebra/implementation/series/rat/nodes.hh>
00023 
00024 # include <vaucanson/misc/escaper.hh>
00025 
00026 namespace vcsn {
00027 
00028   namespace rat {
00029 
00031 
00032 
00034     inline
00035     int
00036     print_mode()
00037     {
00038       static const int idx = std::ios::xalloc();
00039       return idx;
00040     }
00041 
00043     inline
00044     int
00045     zero()
00046     {
00047       static const int idx = std::ios::xalloc();
00048       return idx;
00049     }
00050 
00052     inline
00053     int
00054     id()
00055     {
00056       static const int idx = std::ios::xalloc();
00057       return idx;
00058     }
00059 
00061 
00062     /*------------.
00063     | DumpVisitor |
00064     `------------*/
00065 
00066     template <class Word, class Weight, typename Semiring, typename Monoid>
00067     class DumpVisitor : public ConstNodeVisitor<Word, Weight>
00068     {
00069     public:
00070 
00071       // Type helpers.
00072       typedef Word                                      monoid_elt_value_t;
00073       typedef Weight                                    semiring_elt_value_t;
00074       typedef Node<Word, Weight>                        node_t;
00075       typedef algebra::MonoidRep<Monoid>                monoid_rep_t;
00076       typedef boost::shared_ptr<monoid_rep_t>           shared_monoid_rep_t;
00077       typedef algebra::SeriesRep<Semiring, Monoid>      series_rep_t;
00078       typedef boost::shared_ptr<series_rep_t>           shared_series_rep_t;
00079       typedef algebra::MonoidRepDefault<Monoid>         default_monoid_rep_t;
00080       typedef algebra::SeriesRepDefault<Semiring, Monoid>
00081         default_series_rep_t;
00082 
00083       DumpVisitor(std::ostream& ostr,
00084                   const Monoid& monoid,
00085                   shared_series_rep_t sr = default_series_rep_t::
00086                   get_instance())
00087         : ostr_(ostr),
00088           monoid_(monoid),
00089           monoid_rep_(monoid.representation()),
00090           series_rep_(sr)
00091       {
00092         if (not ostr_.pword(rat::zero()))
00093           ostr_ << setzero(series_rep_->zero);
00094 
00095         if (not ostr_.pword(rat::id()))
00096           ostr_ << setid(monoid_rep_->empty);
00097       }
00098 
00099       virtual
00100       ~DumpVisitor()
00101       {
00102         ostr_.flush();
00103       }
00104 
00105     protected:
00106 
00107       void
00108       enclose_if(const bool cond, const node_t* node)
00109       {
00110         if (cond)
00111           {
00112             ostr_ << series_rep_->open_par;
00113             node->accept(*this);
00114             ostr_ << series_rep_->close_par;
00115           }
00116         else
00117           node->accept(*this);
00118       }
00119 
00120       enum
00121         {
00122           NODE_LWEIGHT  = Node<Word, Weight>::lweight,
00123           NODE_RWEIGHT  = Node<Word, Weight>::rweight,
00124           NODE_PROD     = Node<Word, Weight>::prod,
00125           NODE_SUM      = Node<Word, Weight>::sum,
00126         };
00127 
00128       void
00129       product_print_child(const node_t* child)
00130       {
00131         switch (child->what())
00132           {
00133           case NODE_SUM:
00134             // If MODE_SUM is already set, there is no need to enclose the
00135             // child, since it will be done in sum().
00136             enclose_if(not (ostr_.iword(print_mode()) & MODE_ADD), child);
00137             break;
00138           default:
00139             child->accept(*this);
00140             break;
00141           }
00142       }
00143 
00144     public:
00145 
00146       virtual
00147       void
00148       product(const node_t* lhs, const node_t* rhs)
00149       {
00150         const long verbose = ostr_.iword(print_mode()) & MODE_MUL;
00151 
00152         if (verbose)
00153           ostr_ << series_rep_->open_par;
00154 
00155         product_print_child(lhs);
00156         ostr_ << series_rep_->times;
00157         product_print_child(rhs);
00158 
00159         if (verbose)
00160           ostr_ << series_rep_->close_par;
00161       }
00162 
00163       virtual
00164       void
00165       sum(const node_t* lhs, const node_t* rhs)
00166       {
00167         const long verbose = ostr_.iword(print_mode()) & MODE_ADD;
00168 
00169         if (verbose)
00170           ostr_ << series_rep_->open_par;
00171 
00172         lhs->accept(*this);
00173         ostr_ << series_rep_->plus;
00174         rhs->accept(*this);
00175 
00176         if (verbose)
00177           ostr_ << series_rep_->close_par;
00178       }
00179 
00180       virtual
00181       void
00182       star(const node_t* node)
00183       {
00184         const long      mode = ostr_.iword(print_mode());
00185         const unsigned  node_type = node->what();
00186 
00187         switch (node_type)
00188           {
00189           case NODE_SUM:
00190             enclose_if(not (mode & MODE_ADD), node);
00191             break;
00192           case NODE_PROD:
00193             enclose_if(not (mode & MODE_MUL), node);
00194             break;
00195           case NODE_LWEIGHT:
00196             enclose_if(not (mode & MODE_LWEIGHT), node);
00197             break;
00198           case NODE_RWEIGHT:
00199             enclose_if(not (mode & MODE_RWEIGHT), node);
00200             break;
00201           default:
00202             enclose_if(mode & MODE_STAR, node);
00203             break;
00204           }
00205         ostr_ << series_rep_->star;
00206       }
00207 
00208       virtual
00209       void
00210       left_weight(const semiring_elt_value_t& w, const node_t* node)
00211       {
00212         const long      mode = ostr_.iword(print_mode());
00213         const unsigned  node_type = node->what();
00214         long            verbose;
00215         bool            enclose_all (false);
00216 
00217         switch (node_type)
00218           {
00219           case NODE_PROD:
00220             verbose = not (mode & MODE_MUL);
00221             break;
00222           case NODE_SUM:
00223             verbose = not (mode & MODE_ADD);
00224             break;
00225           case NODE_LWEIGHT:
00226             verbose = not (mode & MODE_LWEIGHT);
00227             break;
00228           case NODE_RWEIGHT:
00229             verbose = not (mode & MODE_RWEIGHT);
00230             break;
00231           default:
00232             verbose = false;
00233             enclose_all = mode & MODE_LWEIGHT;
00234             break;
00235           }
00236 
00237         if (enclose_all)
00238           ostr_ << series_rep_->open_par;
00239 
00240         ostr_ << series_rep_->open_weight << w
00241               << series_rep_->close_weight << series_rep_->spaces.front();
00242         enclose_if(verbose, node);
00243 
00244         if (enclose_all)
00245           ostr_ << series_rep_->close_par;
00246       }
00247 
00248       virtual
00249       void
00250       right_weight(const semiring_elt_value_t& w, const node_t* node)
00251       {
00252         const long      mode = ostr_.iword(print_mode());
00253         const unsigned  node_type = node->what();
00254         long            verbose;
00255         bool            enclose_all (false);
00256 
00257         switch (node_type)
00258           {
00259           case NODE_PROD:
00260             verbose = not (mode & MODE_MUL);
00261             break;
00262           case NODE_SUM:
00263             verbose = not (mode & MODE_ADD);
00264             break;
00265           case NODE_LWEIGHT:
00266             verbose = not (mode & MODE_LWEIGHT);
00267             break;
00268           case NODE_RWEIGHT:
00269             verbose = not (mode & MODE_RWEIGHT);
00270             break;
00271           default:
00272             verbose = false;
00273             enclose_all = mode & MODE_RWEIGHT;
00274             break;
00275           }
00276 
00277         if (enclose_all)
00278           ostr_ << series_rep_->open_par;
00279 
00280         enclose_if(verbose, node);
00281         ostr_ << series_rep_->spaces.front() << series_rep_->open_weight
00282               << w << series_rep_->close_weight;
00283 
00284         if (enclose_all)
00285           ostr_ << series_rep_->close_par;
00286       }
00287 
00288       virtual
00289       void
00290       constant(const monoid_elt_value_t& m)
00291       {
00292         op_rout(monoid_, ostr_, m);
00293       }
00294 
00295       virtual
00296       void
00297       zero()
00298       {
00299         // FIXME: factor with constant.
00300         ostr_ << *static_cast<const std::string*> (ostr_.pword(rat::zero()));
00301       }
00302 
00303       virtual
00304       void
00305       one()
00306       {
00307         // FIXME: factor with constant.
00308         ostr_ << *static_cast<const std::string*> (ostr_.pword(rat::id()));
00309       }
00310 
00311     protected:
00312       std::ostream&     ostr_;
00313       const Monoid&     monoid_;
00314       shared_monoid_rep_t monoid_rep_;
00315       shared_series_rep_t series_rep_;
00316     };
00317 
00318     /*------------.
00319     | operator << |
00320     `------------*/
00321 
00322 //    template <class Word, class Weight>
00323 //    std::ostream&
00324 //    operator << (std::ostream& ostr, const exp<Word, Weight>& e)
00325 //    {
00326 //      DumpVisitor<Word, Weight, true, true> v (ostr);
00327 //      e.accept(v);
00328 //      return ostr;
00329 //    }
00330 
00331     /*------.
00332     | setpm |
00333     `------*/
00334 
00335     inline
00336     setpm::setpm(print_mode_t mode) : mode_ (mode)
00337     {
00338     }
00339 
00340     inline
00341     std::ostream&
00342     setpm::operator () (std::ostream& ostr) const
00343     {
00344       ostr.iword(print_mode()) = mode_;
00345       return ostr;
00346     }
00347 
00348     /*------.
00349     | getpm |
00350     `------*/
00351 
00352     inline
00353     print_mode_t
00354     getpm(std::ostream& ostr)
00355     {
00356       return print_mode_t (ostr.iword(print_mode()));
00357     }
00358 
00359     /*--------.
00360     | setzero |
00361     `--------*/
00362 
00363     inline
00364     setzero::setzero(const std::string& zero) : z_ (zero)
00365     {
00366     }
00367 
00368     inline
00369     std::ostream&
00370     setzero::operator () (std::ostream& ostr) const
00371     {
00372       const int idx = zero();
00373 
00374       if (not ostr.pword(idx))
00375         ostr.register_callback(misc::pword_delete<std::string>, idx);
00376       else
00377         delete static_cast<std::string*> (ostr.pword(idx));
00378       ostr.pword(idx) = new std::string (z_);
00379       return ostr;
00380     }
00381 
00382     /*------.
00383     | setid |
00384     `------*/
00385 
00386     inline
00387     setid::setid(const std::string& id) : i_ (id)
00388     {
00389     }
00390 
00391     inline
00392     std::ostream&
00393     setid::operator () (std::ostream& ostr) const
00394     {
00395       const int idx = id();
00396 
00397       if (not ostr.pword(idx))
00398         ostr.register_callback(misc::pword_delete<std::string>, idx);
00399       else
00400         delete static_cast<std::string*> (ostr.pword(idx));
00401       ostr.pword(idx) = new std::string (i_);
00402       return ostr;
00403     }
00404 
00405   } // rat
00406 
00407 } // vcsn
00408 
00409 #endif // ! VCSN_ALGEBRA_IMPLEMENTATION_SERIES_RAT_DUMP_VISITOR_HXX