Vaucanson  1.4.1
dump_visitor.hxx
1 // dump_visitor.hxx: this file is part of the Vaucanson project.
2 //
3 // Vaucanson, a generic library for finite state machines.
4 //
5 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2010 The Vaucanson Group.
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
11 //
12 // The complete GNU General Public Licence Notice can be found as the
13 // `COPYING' file in the root directory.
14 //
15 // The Vaucanson Group consists of people listed in the `AUTHORS' file.
16 //
17 #ifndef VCSN_ALGEBRA_IMPLEMENTATION_SERIES_RAT_DUMP_VISITOR_HXX
18 # define VCSN_ALGEBRA_IMPLEMENTATION_SERIES_RAT_DUMP_VISITOR_HXX
19 
20 # include <vaucanson/algebra/concept/letter.hh>
21 # include <vaucanson/algebra/implementation/series/rat/dump_visitor.hh>
22 # include <vaucanson/algebra/implementation/series/rat/nodes.hh>
23 
24 # include <vaucanson/misc/escaper.hh>
25 
26 namespace vcsn {
27 
28  namespace rat {
29 
31 
32 
34  inline
35  int
36  print_mode()
37  {
38  static const int idx = std::ios::xalloc();
39  return idx;
40  }
41 
43  inline
44  int
45  zero()
46  {
47  static const int idx = std::ios::xalloc();
48  return idx;
49  }
50 
52  inline
53  int
54  id()
55  {
56  static const int idx = std::ios::xalloc();
57  return idx;
58  }
59 
61 
62  /*------------.
63  | DumpVisitor |
64  `------------*/
65 
66  template <class Word, class Weight, typename Semiring, typename Monoid>
67  class DumpVisitor : public ConstNodeVisitor<Word, Weight>
68  {
69  public:
70 
71  // Type helpers.
72  typedef Word monoid_elt_value_t;
73  typedef Weight semiring_elt_value_t;
74  typedef Node<Word, Weight> node_t;
75  typedef algebra::MonoidRep<Monoid> monoid_rep_t;
76  typedef boost::shared_ptr<monoid_rep_t> shared_monoid_rep_t;
77  typedef algebra::SeriesRep<Semiring, Monoid> series_rep_t;
78  typedef boost::shared_ptr<series_rep_t> shared_series_rep_t;
79  typedef algebra::MonoidRepDefault<Monoid> default_monoid_rep_t;
80  typedef algebra::SeriesRepDefault<Semiring, Monoid>
81  default_series_rep_t;
82 
83  DumpVisitor(std::ostream& ostr,
84  const Monoid& monoid,
85  shared_series_rep_t sr = default_series_rep_t::
86  get_instance())
87  : ostr_(ostr),
88  monoid_(monoid),
89  monoid_rep_(monoid.representation()),
90  series_rep_(sr)
91  {
92  if (not ostr_.pword(rat::zero()))
93  ostr_ << setzero(series_rep_->zero);
94 
95  if (not ostr_.pword(rat::id()))
96  ostr_ << setid(monoid_rep_->empty);
97  }
98 
99  virtual
100  ~DumpVisitor()
101  {
102  ostr_.flush();
103  }
104 
105  protected:
106 
107  void
108  enclose_if(const bool cond, const node_t* node)
109  {
110  if (cond)
111  {
112  ostr_ << series_rep_->open_par;
113  node->accept(*this);
114  ostr_ << series_rep_->close_par;
115  }
116  else
117  node->accept(*this);
118  }
119 
120  enum
121  {
122  NODE_LWEIGHT = Node<Word, Weight>::lweight,
123  NODE_RWEIGHT = Node<Word, Weight>::rweight,
124  NODE_PROD = Node<Word, Weight>::prod,
125  NODE_SUM = Node<Word, Weight>::sum,
126  };
127 
128  void
129  product_print_child(const node_t* child)
130  {
131  switch (child->what())
132  {
133  case NODE_SUM:
134  // If MODE_SUM is already set, there is no need to enclose the
135  // child, since it will be done in sum().
136  enclose_if(not (ostr_.iword(print_mode()) & MODE_ADD), child);
137  break;
138  default:
139  child->accept(*this);
140  break;
141  }
142  }
143 
144  public:
145 
146  virtual
147  void
148  product(const node_t* lhs, const node_t* rhs)
149  {
150  const long verbose = ostr_.iword(print_mode()) & MODE_MUL;
151 
152  if (verbose)
153  ostr_ << series_rep_->open_par;
154 
155  product_print_child(lhs);
156  ostr_ << series_rep_->times;
157  product_print_child(rhs);
158 
159  if (verbose)
160  ostr_ << series_rep_->close_par;
161  }
162 
163  virtual
164  void
165  sum(const node_t* lhs, const node_t* rhs)
166  {
167  const long verbose = ostr_.iword(print_mode()) & MODE_ADD;
168 
169  if (verbose)
170  ostr_ << series_rep_->open_par;
171 
172  lhs->accept(*this);
173  ostr_ << series_rep_->plus;
174  rhs->accept(*this);
175 
176  if (verbose)
177  ostr_ << series_rep_->close_par;
178  }
179 
180  virtual
181  void
182  star(const node_t* node)
183  {
184  const long mode = ostr_.iword(print_mode());
185  const unsigned node_type = node->what();
186 
187  switch (node_type)
188  {
189  case NODE_SUM:
190  enclose_if(not (mode & MODE_ADD), node);
191  break;
192  case NODE_PROD:
193  enclose_if(not (mode & MODE_MUL), node);
194  break;
195  case NODE_LWEIGHT:
196  enclose_if(not (mode & MODE_LWEIGHT), node);
197  break;
198  case NODE_RWEIGHT:
199  enclose_if(not (mode & MODE_RWEIGHT), node);
200  break;
201  default:
202  enclose_if(mode & MODE_STAR, node);
203  break;
204  }
205  ostr_ << series_rep_->star;
206  }
207 
208  virtual
209  void
210  left_weight(const semiring_elt_value_t& w, const node_t* node)
211  {
212  const long mode = ostr_.iword(print_mode());
213  const unsigned node_type = node->what();
214  long verbose;
215  bool enclose_all (false);
216 
217  switch (node_type)
218  {
219  case NODE_PROD:
220  verbose = not (mode & MODE_MUL);
221  break;
222  case NODE_SUM:
223  verbose = not (mode & MODE_ADD);
224  break;
225  case NODE_LWEIGHT:
226  verbose = not (mode & MODE_LWEIGHT);
227  break;
228  case NODE_RWEIGHT:
229  verbose = not (mode & MODE_RWEIGHT);
230  break;
231  default:
232  verbose = false;
233  enclose_all = mode & MODE_LWEIGHT;
234  break;
235  }
236 
237  if (enclose_all)
238  ostr_ << series_rep_->open_par;
239 
240  ostr_ << series_rep_->open_weight << w
241  << series_rep_->close_weight << series_rep_->spaces.front();
242  enclose_if(verbose, node);
243 
244  if (enclose_all)
245  ostr_ << series_rep_->close_par;
246  }
247 
248  virtual
249  void
250  right_weight(const semiring_elt_value_t& w, const node_t* node)
251  {
252  const long mode = ostr_.iword(print_mode());
253  const unsigned node_type = node->what();
254  long verbose;
255  bool enclose_all (false);
256 
257  switch (node_type)
258  {
259  case NODE_PROD:
260  verbose = not (mode & MODE_MUL);
261  break;
262  case NODE_SUM:
263  verbose = not (mode & MODE_ADD);
264  break;
265  case NODE_LWEIGHT:
266  verbose = not (mode & MODE_LWEIGHT);
267  break;
268  case NODE_RWEIGHT:
269  verbose = not (mode & MODE_RWEIGHT);
270  break;
271  default:
272  verbose = false;
273  enclose_all = mode & MODE_RWEIGHT;
274  break;
275  }
276 
277  if (enclose_all)
278  ostr_ << series_rep_->open_par;
279 
280  enclose_if(verbose, node);
281  ostr_ << series_rep_->spaces.front() << series_rep_->open_weight
282  << w << series_rep_->close_weight;
283 
284  if (enclose_all)
285  ostr_ << series_rep_->close_par;
286  }
287 
288  virtual
289  void
290  constant(const monoid_elt_value_t& m)
291  {
292  op_rout(monoid_, ostr_, m);
293  }
294 
295  virtual
296  void
297  zero()
298  {
299  // FIXME: factor with constant.
300  ostr_ << *static_cast<const std::string*> (ostr_.pword(rat::zero()));
301  }
302 
303  virtual
304  void
305  one()
306  {
307  // FIXME: factor with constant.
308  ostr_ << *static_cast<const std::string*> (ostr_.pword(rat::id()));
309  }
310 
311  protected:
312  std::ostream& ostr_;
313  const Monoid& monoid_;
314  shared_monoid_rep_t monoid_rep_;
315  shared_series_rep_t series_rep_;
316  };
317 
318  /*------------.
319  | operator << |
320  `------------*/
321 
322 // template <class Word, class Weight>
323 // std::ostream&
324 // operator << (std::ostream& ostr, const exp<Word, Weight>& e)
325 // {
326 // DumpVisitor<Word, Weight, true, true> v (ostr);
327 // e.accept(v);
328 // return ostr;
329 // }
330 
331  /*------.
332  | setpm |
333  `------*/
334 
335  inline
336  setpm::setpm(print_mode_t mode) : mode_ (mode)
337  {
338  }
339 
340  inline
341  std::ostream&
342  setpm::operator () (std::ostream& ostr) const
343  {
344  ostr.iword(print_mode()) = mode_;
345  return ostr;
346  }
347 
348  /*------.
349  | getpm |
350  `------*/
351 
352  inline
353  print_mode_t
354  getpm(std::ostream& ostr)
355  {
356  return print_mode_t (ostr.iword(print_mode()));
357  }
358 
359  /*--------.
360  | setzero |
361  `--------*/
362 
363  inline
364  setzero::setzero(const std::string& zero) : z_ (zero)
365  {
366  }
367 
368  inline
369  std::ostream&
370  setzero::operator () (std::ostream& ostr) const
371  {
372  const int idx = zero();
373 
374  if (not ostr.pword(idx))
375  ostr.register_callback(misc::pword_delete<std::string>, idx);
376  else
377  delete static_cast<std::string*> (ostr.pword(idx));
378  ostr.pword(idx) = new std::string (z_);
379  return ostr;
380  }
381 
382  /*------.
383  | setid |
384  `------*/
385 
386  inline
387  setid::setid(const std::string& id) : i_ (id)
388  {
389  }
390 
391  inline
392  std::ostream&
393  setid::operator () (std::ostream& ostr) const
394  {
395  const int idx = id();
396 
397  if (not ostr.pword(idx))
398  ostr.register_callback(misc::pword_delete<std::string>, idx);
399  else
400  delete static_cast<std::string*> (ostr.pword(idx));
401  ostr.pword(idx) = new std::string (i_);
402  return ostr;
403  }
404 
405  } // rat
406 
407 } // vcsn
408 
409 #endif // ! VCSN_ALGEBRA_IMPLEMENTATION_SERIES_RAT_DUMP_VISITOR_HXX