Vcsn  2.1
Be Rational
nullableset.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <memory>
4 #include <set>
5 #include <sstream>
6 
7 #include <vcsn/alphabets/setalpha.hh> // intersect
8 #include <vcsn/core/kind.hh>
9 #include <vcsn/labelset/fwd.hh>
12 #include <vcsn/labelset/oneset.hh>
13 #include <vcsn/misc/escape.hh>
14 #include <vcsn/misc/functional.hh>
15 #include <vcsn/misc/raise.hh>
16 
17 namespace vcsn
18 {
19  namespace detail
20  {
27  template <typename LabelSet>
29  {
30  using labelset_t = LabelSet;
31  using value_t = std::pair<typename labelset_t::value_t, bool>;
32 
33  ATTRIBUTE_PURE
34  static constexpr value_t
35  one()
36  {
37  return value_t{labelset_t::special(), true};
38  }
39 
40  ATTRIBUTE_PURE
41  static constexpr value_t
43  {
44  return value_t{labelset_t::special(), false};
45  }
46 
47  template <typename Ls>
48  ATTRIBUTE_PURE
50  is_one_(const value_t& l)
51  {
52  return std::get<1>(l) || Ls::is_one(get_value(l));
53  }
54 
55  template <typename Ls>
56  ATTRIBUTE_PURE
58  is_one_(const value_t& l)
59  {
60  return std::get<1>(l);
61  }
62 
63  ATTRIBUTE_PURE
64  static bool
65  is_one(const value_t& l)
66  {
67  return is_one_<labelset_t>(l);
68  }
69 
70  template <typename Value>
71  static Value
72  transpose(const labelset_t& ls, Value l)
73  {
74  // This is not robust enough: Value is word_t, then it's not
75  // valid to call is_one on it. Since I'm unsure of the future
76  // of nullableset, let's not waste time on this now.
77  if (is_one(l))
78  return l;
79  else
80  return {ls.transpose(get_value(l)), false};
81  }
82 
83  template <typename... Args>
84  static value_t
85  value(const labelset_t& ls, Args&&... args)
86  {
87  return {ls.value(std::forward<Args>(args)...), false};
88  }
89 
90  ATTRIBUTE_PURE
91  static typename labelset_t::value_t
93  {
94  return std::get<0>(v);
95  }
96  };
97 
104  template <typename GenSet>
105  struct nullable_helper<letterset<GenSet>>
106  {
107  using genset_t = GenSet;
109  using value_t = typename labelset_t::value_t;
110 
111  ATTRIBUTE_PURE
112  static constexpr value_t
114  {
115  return genset_t::special();
116  }
117 
118  ATTRIBUTE_PURE
119  static constexpr value_t
120  one()
121  {
122  return genset_t::one_letter();
123  }
124 
125  ATTRIBUTE_PURE
126  static bool
128  {
129  return l == one();
130  }
131 
132  template <typename Value>
133  static Value
134  transpose(const labelset_t& ls, const Value& l)
135  {
136  return ls.transpose(l);
137  }
138 
139  template <typename... Args>
140  static value_t
141  value(const labelset_t& ls, Args&&... args)
142  {
143  return ls.value(std::forward<Args>(args)...);
144  }
145 
146  ATTRIBUTE_PURE
147  static value_t
149  {
150  return v;
151  }
152  };
153  }
154 
156  template <typename LabelSet>
157  class nullableset
158  {
159  public:
160  using labelset_t = LabelSet;
161  using labelset_ptr = std::shared_ptr<const labelset_t>;
165 
166  using value_t = typename helper_t::value_t;
167  using letter_t = typename labelset_t::letter_t;
168  using word_t = typename labelset_t::word_t;
169 
170  private:
174 
175  public:
177  : ls_{ls}
178  {}
179 
180  nullableset(const labelset_t& ls = {})
181  : nullableset{std::make_shared<const labelset_t>(ls)}
182  {}
183 
184  static symbol sname()
185  {
186  static symbol res("nullableset<" + labelset_t::sname() + '>');
187  return res;
188  }
189 
191  static nullableset make(std::istream& is)
192  {
193  // name: nullableset<lal_char(abc)>.
194  // ^^^^^^^^^^^^
195  // labelset
196  eat(is, "nullableset<");
197  auto ls = labelset_t::make(is);
198  eat(is, '>');
199  return {ls};
200  }
201 
205  bool open(bool o) const
206  {
207  return this->ls_->open(o);
208  }
209 
210  static constexpr bool
212  {
213  return true;
214  }
215 
216  static constexpr bool
218  {
219  return false;
220  }
221 
222  static constexpr bool
224  {
225  return labelset_t::is_letterized();
226  }
227 
228  static constexpr bool is_free()
229  {
230  return false;
231  }
232 
233  ATTRIBUTE_PURE
234  static constexpr value_t
235  one()
236  {
237  return helper_t::one();
238  }
239 
240  ATTRIBUTE_PURE
241  static bool
243  {
244  return helper_t::is_one(l);
245  }
246 
247  bool
249  {
250  return is_one(v) || ls_->is_valid(get_value(v));
251  }
252 
254  auto
255  genset() const
256  -> decltype(this->ls_->genset())
257  {
258  return ls_->genset();
259  }
260 
261  value_t
263  {
264  return v;
265  }
266 
267  value_t
268  conv(oneset, typename oneset::value_t) const
269  {
270  return one();
271  }
272 
276  template <typename LabelSet_>
277  value_t
278  conv(const LabelSet_& ls, typename LabelSet_::value_t v) const
279  {
280  return value(ls_->conv(ls, v));
281  }
282 
283  const labelset_ptr labelset() const
284  {
285  return ls_;
286  }
287 
288  template <typename... Args>
289  value_t
290  value(Args&&... args) const
291  {
292  return helper_t::value(*ls_, std::forward<Args>(args)...);
293  }
294 
295  word_t
296  word(const value_t& l) const
297  {
298  if (is_one(l))
299  return make_wordset(*labelset()).one();
300  else
301  return ls_->word(get_value(l));
302  }
303 
305  auto static
307  -> decltype(labelset_t::letters_of(v))
308  {
309  return labelset_t::letters_of(v);
310  }
311 
314  auto
316  -> decltype(ls_->letters_of_padded(v, l))
317  {
318  return ls_->letters_of_padded(v, l);
319  }
320 
321  auto
323  -> decltype(this->letters_of_padded(this->word(v), l))
324  {
325  return letters_of_padded(word(v), l);
326  }
327 
329  static bool equal(const value_t& l, const value_t& r)
330  {
331  if (is_one(l))
332  return is_one(r);
333  else
334  return !is_one(r) && labelset_t::equal(get_value(l), get_value(r));
335  }
336 
338  static bool less(const value_t& l, const value_t& r)
339  {
340  if (is_one(r))
341  return false;
342  else if (is_one(l))
343  return true;
344  else
345  return labelset_t::less(get_value(l), get_value(r));
346  }
347 
349  value_t lgcd(const value_t& l, const value_t& r) const
350  {
351  if (equal(l, r))
352  return l;
353  else if (is_one(l) || is_one(r))
354  return one();
355  else
356  return value(ls_->lgcd(get_value(l), get_value(r)));
357  }
358 
360  value_t ldiv(const value_t& l, const value_t& r) const
361  {
362  if (equal(l, r))
363  return one();
364  else if (is_one(l))
365  return r;
366  else if (is_one(r))
367  raise(*this, ": ldiv: invalid arguments: ",
368  to_string(*this, l), ", ", to_string(*this, r));
369  else
370  return value(ls_->ldiv(get_value(l), get_value(r)));
371  }
372 
373  static value_t
375  {
376  return helper_t::special();
377  }
378 
379  static bool
381  {
382  return !is_one(v) && labelset_t::is_special(get_value(v));
383  }
384 
385  static size_t size(const value_t& v)
386  {
387  return is_one(v) ? 0 : labelset_t::size(get_value(v));
388  }
389 
390  // FIXME: specialize for both implementation.
391  static size_t hash(const value_t& v)
392  {
393  // Do not use get_value when is_one. Let's hash one() as 0.
394  return is_one(v) ? 0 : labelset_t::hash(get_value(v));
395  }
396 
397  letter_t
398  get_letter(std::istream& i, bool quoted = true) const
399  {
400  return ls_->get_letter(i, quoted);
401  }
402 
404  value_t
405  conv(std::istream& i, bool quoted = true) const
406  {
407  // Check for '\e', otherwise pass it to the inner labelset.
408  if (i.good() && i.peek() == '\\')
409  {
410  i.ignore();
411  int c = i.peek();
412  if (c == 'e')
413  {
414  i.ignore();
415  return {};
416  }
417  else
418  i.unget();
419  }
420  return value(ls_->conv(i, quoted));
421  }
422 
423  template <typename Fun>
424  void convs(std::istream& i, Fun fun) const
425  {
426  ls_->convs(i, fun);
427  }
428 
430  std::ostream&
431  print(const value_t& l, std::ostream& o,
432  format fmt = {}) const
433  {
434  if (is_one(l))
435  o << (fmt == format::latex ? "\\varepsilon" : "\\e");
436  else
437  ls_->print(get_value(l), o, fmt);
438  return o;
439  }
440 
441  value_t
442  zero() const
443  {
444  return value(ls_->zero());
445  }
446 
447  bool
448  is_zero(const value_t& v) const
449  {
450  return !is_one(v) && ls_->is_zero(get_value(v));
451  }
452 
453  bool
454  is_letter(const value_t& v) const
455  {
456  return !is_one(v) && ls_->is_letter(get_value(v));
457  }
458 
460  template <typename Value>
461  Value
462  transpose(const Value& l) const
463  {
464  return helper_t::transpose(*ls_, l);
465  }
466 
468  std::ostream&
469  print_set(std::ostream& o, format fmt = {}) const
470  {
471  switch (fmt.kind())
472  {
473  case format::latex:
474  o << "(";
475  ls_->print_set(o, fmt);
476  o << ")^?";
477  break;
478 
479  case format::text:
480  o << "nullableset<";
481  ls_->print_set(o, fmt);
482  o << '>';
483  break;
484 
485  case format::raw:
486  assert(0);
487  break;
488  }
489 
490  return o;
491  }
492 
494  static typename labelset_t::value_t
495  get_value(const value_t& v)
496  {
497  assert(!is_one(v));
498  return helper_t::get_value(v);
499  }
500  };
501 
502  namespace detail
503  {
505  template <typename LabelSet>
506  struct letterized_traits<nullableset<LabelSet>>
507  {
508  using traits = letterized_traits<LabelSet>;
509  static constexpr bool is_letterized = traits::is_letterized;
510 
511  using labelset_t = typename traits::labelset_t;
512 
513  static labelset_t labelset(const nullableset<LabelSet>& ls)
514  {
515  return make_letterized(*ls.labelset());
516  }
517  };
518 
520  template <typename LabelSet>
521  struct nullableset_traits<nullableset<LabelSet>>
522  {
523  using type = nullableset<LabelSet>;
524  static type value(const nullableset<LabelSet>& ls)
525  {
526  return ls;
527  }
528  };
529 
530  template <typename LabelSet>
531  struct proper_traits<nullableset<LabelSet>>
532  {
533  using type = LabelSet;
534  static type value(const nullableset<LabelSet>& ls)
535  {
536  return *ls.labelset();
537  }
538  };
539 
541  template <typename LabelSet>
542  struct law_traits<nullableset<LabelSet>>
543  {
544  using type = law_t<LabelSet>;
545  static type value(const nullableset<LabelSet>& ls)
546  {
547  return make_wordset(*ls.labelset());
548  }
549  };
550 
551  /*-------.
552  | Join. |
553  `-------*/
554 
556  template <typename LS>
557  struct join_impl<oneset, LS,
558  enable_if_t<!LS::has_one()>>
559  {
560  using type = nullableset<LS>;
561  static type join(const oneset&, const LS& ls)
562  {
563  return {ls};
564  }
565  };
566 
568  template <typename LS>
569  struct join_impl<oneset, LS,
570  enable_if_t<LS::has_one()>>
571  {
572  using type = LS;
573  static type join(const oneset&, const LS& ls)
574  {
575  return ls;
576  }
577  };
578 
580  template <typename LS1, typename LS2>
581  struct join_impl<nullableset<LS1>, LS2>
582  {
583  using type = nullableset<join_t<LS1, LS2>>;
584  static type join(const nullableset<LS1>& ls1, const LS2& ls2)
585  {
586  return {::vcsn::join(*ls1.labelset(), ls2)};
587  }
588  };
589 
594  template <typename LS1, typename LS2>
595  struct join_impl<nullableset<LS1>, nullableset<LS2>>
596  {
597  using type = nullableset<join_t<LS1, LS2>>;
598  static type join(const nullableset<LS1>& ls1,
599  const nullableset<LS2>& ls2)
600  {
601  return {::vcsn::join(*ls1.labelset(), *ls2.labelset())};
602  }
603  };
604  }
605 
606  /*-------.
607  | Meet. |
608  `-------*/
609 
610 #define DEFINE(Lhs, Rhs, Res) \
611  template <typename GenSet> \
612  Res \
613  meet(const Lhs& lhs, const Rhs& rhs) \
614  { \
615  return {intersection(lhs.genset(), rhs.genset())}; \
616  }
617 
619  DEFINE(nullableset<letterset<GenSet>>,
620  nullableset<letterset<GenSet>>, nullableset<letterset<GenSet>>);
621 
622  DEFINE(letterset<GenSet>,
623  nullableset<letterset<GenSet>>, nullableset<letterset<GenSet>>);
624 
625  DEFINE(nullableset<letterset<GenSet>>,
626  letterset<GenSet>, nullableset<letterset<GenSet>>);
627 
628  template <typename Lls, typename Rls>
629  nullableset<meet_t<Lls, Rls>>
630  meet(const nullableset<Lls>& lhs, const nullableset<Rls>& rhs)
631  {
632  return nullableset<meet_t<Lls, Rls>>{meet(*lhs.labelset(),
633  *rhs.labelset())};
634  }
635 
636 #undef DEFINE
637 
638 }
bool open(bool o) const
Whether unknown letters should be added, or rejected.
Definition: nullableset.hh:205
typename labelset_t::letter_t letter_t
Definition: nullableset.hh:167
static bool less(const value_t &l, const value_t &r)
Whether l < r.
Definition: nullableset.hh:338
static Value transpose(const labelset_t &ls, Value l)
Definition: nullableset.hh:72
static ATTRIBUTE_PURE labelset_t::value_t get_value(const value_t &v)
Definition: nullableset.hh:92
static symbol sname()
Definition: nullableset.hh:184
static ATTRIBUTE_PURE constexpr value_t special()
Definition: nullableset.hh:113
Implementation of labels are letters.
Definition: fwd.hh:10
static ATTRIBUTE_PURE constexpr value_t one()
Definition: nullableset.hh:35
static value_t value(const labelset_t &ls, Args &&...args)
Definition: nullableset.hh:85
auto genset() const -> decltype(this->ls_->genset())
The generators. Meaningful for labelsets only.
Definition: nullableset.hh:255
weightset_mixin< detail::r_impl > r
Definition: fwd.hh:54
static constexpr bool is_letterized()
Definition: nullableset.hh:223
static size_t size(const value_t &v)
Definition: nullableset.hh:385
value_t conv(oneset, typename oneset::value_t) const
Definition: nullableset.hh:268
static value_t special()
Definition: nullableset.hh:374
typename helper_t::value_t value_t
Definition: nullableset.hh:166
nullableset(const labelset_t &ls={})
Definition: nullableset.hh:180
std::istringstream is
The input stream: the specification to translate.
Definition: translate.cc:372
Value transpose(const Value &l) const
Mirror label.
Definition: nullableset.hh:462
std::pair< typename labelset_t::value_t, bool > value_t
Definition: nullableset.hh:31
char eat(std::istream &is, char c)
Check lookahead character and advance.
Definition: stream.cc:37
Empty labels, for LAO.
Definition: empty.hh:8
letter_t get_letter(std::istream &i, bool quoted=true) const
Definition: nullableset.hh:398
std::ostream & print(const value_t &l, std::ostream &o, format fmt={}) const
Print label to stream.
Definition: nullableset.hh:431
typename std::enable_if< Cond, T >::type enable_if_t
Definition: type_traits.hh:16
static size_t hash(const value_t &v)
Definition: nullableset.hh:391
bool is_zero(const value_t &v) const
Definition: nullableset.hh:448
value_t zero() const
Definition: nullableset.hh:442
Add support for an empty word to a LabelSet that does not provide such special label to this end...
Definition: nullableset.hh:28
static value_t value(const labelset_t &ls, Args &&...args)
Definition: nullableset.hh:141
value_t ldiv(const value_t &l, const value_t &r) const
Compute l \ r = l^{-1}r.
Definition: nullableset.hh:360
static ATTRIBUTE_PURE bool is_one(value_t l)
Definition: nullableset.hh:127
value_t value(Args &&...args) const
Definition: nullableset.hh:290
static ATTRIBUTE_PURE bool is_one(const value_t &l)
Definition: nullableset.hh:65
static constexpr bool is_free()
Definition: nullableset.hh:228
std::ostream & print_set(std::ostream &o, format fmt={}) const
Print labelset description.
Definition: nullableset.hh:469
auto letters_of_padded(const word_t &v, letter_t l) const -> decltype(ls_->letters_of_padded(v, l))
Prepare to iterate over the letters of v.
Definition: nullableset.hh:315
std::shared_ptr< const labelset_t > labelset_ptr
Definition: nullableset.hh:161
An input/output format.
Definition: format.hh:11
static ATTRIBUTE_PURE bool is_one(value_t l)
Definition: nullableset.hh:242
bool is_letter(const value_t &v) const
Definition: nullableset.hh:454
word_t word(const value_t &l) const
Definition: nullableset.hh:296
static bool is_special(const value_t &v)
Definition: nullableset.hh:380
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
static constexpr bool has_one()
Definition: nullableset.hh:211
Implementation of labels are ones: there is a single instance of label.
Definition: oneset.hh:17
law_t< LabelSet > make_wordset(const LabelSet &ls)
The wordset of a labelset.
Definition: labelset.hh:261
typename labelset_t::word_t word_t
Definition: nullableset.hh:168
size_t size(const ExpSet &rs, const typename ExpSet::value_t &r)
static ATTRIBUTE_PURE constexpr value_t one()
Definition: nullableset.hh:235
static ATTRIBUTE_PURE vcsn::enable_if_t<!Ls::has_one(), bool > is_one_(const value_t &l)
Definition: nullableset.hh:58
const labelset_ptr labelset() const
Definition: nullableset.hh:283
std::string to_string(direction d)
Conversion to string.
Definition: direction.cc:7
void convs(std::istream &i, Fun fun) const
Definition: nullableset.hh:424
static ATTRIBUTE_PURE constexpr value_t one()
Definition: nullableset.hh:120
static ATTRIBUTE_PURE value_t get_value(const value_t &v)
Definition: nullableset.hh:148
value_t conv(const LabelSet_ &ls, typename LabelSet_::value_t v) const
Conversion from another type: first by the wrapped labelset, and then by our wrappers (in case the wr...
Definition: nullableset.hh:278
auto letters_of_padded(value_t v, letter_t l) const -> decltype(this->letters_of_padded(this->word(v), l))
Definition: nullableset.hh:322
value_t conv(std::istream &i, bool quoted=true) const
Read a label from a stream.
Definition: nullableset.hh:405
static nullableset make(std::istream &is)
Build from the description in is.
Definition: nullableset.hh:191
symbol sname()
Definition: name.hh:67
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Definition: symbol.hh:23
static Value transpose(const labelset_t &ls, const Value &l)
Definition: nullableset.hh:134
vcsn::enable_if_t<!is_letterized_t< labelset_t_of< Aut > >{}, bool > is_letterized(const Aut &aut)
Definition: letterize.hh:162
static auto letters_of(const word_t &v) -> decltype(labelset_t::letters_of(v))
Prepare to iterate over the letters of v.
Definition: nullableset.hh:306
value_t value(Args &&...args) const
Value constructor.
Definition: letterset.hh:82
letter_t value_t
Definition: letterset.hh:32
static constexpr bool is_expressionset()
Definition: nullableset.hh:217
bool is_valid(value_t v) const
Definition: nullableset.hh:248
ATTRIBUTE_PURE auto transpose(Args &&...args) const -> decltype(this->genset().transpose(std::forward< Args >(args)...))
value_t lgcd(const value_t &l, const value_t &r) const
The longest common prefix.
Definition: nullableset.hh:349
static labelset_t::value_t get_value(const value_t &v)
The (inner) value when it (the outer value) is not one.
Definition: nullableset.hh:495
labelset_ptr ls_
The wrapped LabelSet.
Definition: nullableset.hh:173
static ATTRIBUTE_PURE vcsn::enable_if_t< Ls::has_one(), bool > is_one_(const value_t &l)
Definition: nullableset.hh:50
static ATTRIBUTE_PURE constexpr value_t special()
Definition: nullableset.hh:42
nullableset(const labelset_ptr &ls)
Definition: nullableset.hh:176
static bool equal(const value_t &l, const value_t &r)
Whether l == r.
Definition: nullableset.hh:329
Implementation of labels are nullables (letter or empty).
Definition: fwd.hh:14
value_t conv(self_t, value_t v) const
Definition: nullableset.hh:262