Vcsn  2.0
Be Rational
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
nullableset.hh
Go to the documentation of this file.
1 #ifndef VCSN_LABELSET_NULLABLESET_HH
2 # define VCSN_LABELSET_NULLABLESET_HH
3 
4 # include <cstring> //strncmp
5 # include <memory>
6 # include <set>
7 # include <sstream>
8 
9 # include <vcsn/alphabets/setalpha.hh> // intersect
10 # include <vcsn/core/kind.hh>
11 # include <vcsn/labelset/fwd.hh>
13 # include <vcsn/labelset/labelset.hh>
14 # include <vcsn/labelset/oneset.hh>
15 # include <vcsn/misc/escape.hh>
16 # include <vcsn/misc/hash.hh>
17 # include <vcsn/misc/raise.hh>
18 
19 namespace vcsn
20 {
21  namespace detail
22  {
25  template <typename LabelSet>
27  {
30  using value_t = std::pair<typename labelset_t::value_t, bool>;
31  using kind_t = typename LabelSet::kind_t;
32 
33  static null make(std::istream& is)
34  {
35  // name: nullableset<lal_char(abc)>.
36  // ^^^^^^^^^^^^
37  // labelset
39  eat(is, '<');
40  auto ls = null::labelset_t::make(is);
41  eat(is, '>');
42  return null{ls};
43  }
44 
45  ATTRIBUTE_PURE
46  static constexpr value_t
47  one()
48  {
49  return value_t{null::labelset_t::special(), true};
50  }
51 
52  ATTRIBUTE_PURE
53  static constexpr value_t
55  {
56  return value_t{null::labelset_t::special(), false};
57  }
58 
59  template <typename Ls>
60  ATTRIBUTE_PURE
61  static typename std::enable_if<Ls::has_one(), bool>::type
63  {
64  return std::get<1>(l) || Ls::is_one(get_value(l));
65  }
66 
67  template <typename Ls>
68  ATTRIBUTE_PURE
69  static typename std::enable_if<!Ls::has_one(), bool>::type
71  {
72  return std::get<1>(l);
73  }
74 
75  ATTRIBUTE_PURE
76  static bool
78  {
79  return is_one_<labelset_t>(l);
80  }
81 
82  template <typename... Args>
83  static value_t
84  value(const labelset_t& ls, Args&&... args)
85  {
86  return {ls.value(std::forward<Args>(args)...), false};
87  }
88 
89  ATTRIBUTE_PURE
90  static typename labelset_t::value_t
91  get_value(const value_t& v)
92  {
93  return std::get<0>(v);
94  }
95  };
96 
99  template <typename GenSet>
100  struct nullable_helper<letterset<GenSet>>
101  {
103  using genset_t = GenSet;
105  using value_t = typename labelset_t::value_t;
107 
108  static null
109  make(std::istream& is)
110  {
111  using genset_t = typename labelset_t::genset_t;
112  // name: lal_char(abc), ratexpset<law_char(xyz), b>.
113  // ^^^ ^^^^ ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
114  // | | | weightset
115  // | | +-- gens
116  // | +-- letter_type
117  // +-- kind
119  if (is.peek() == '_')
120  {
121  eat(is, '_');
122  auto gs = genset_t::make(is);
123  auto ls = labelset_t{gs};
124  return null{ls};
125  }
126  eat(is, '<');
127  auto ls = labelset_t::make(is);
128  eat(is, '>');
129  return null{ls};
130  }
131 
132  ATTRIBUTE_PURE
133  static constexpr typename null::value_t
135  {
136  return genset_t::special();
137  }
138 
139  ATTRIBUTE_PURE
140  static constexpr typename null::value_t
141  one()
142  {
143  return genset_t::one_letter();
144  }
145 
146  ATTRIBUTE_PURE
147  static bool
149  {
150  return l == one();
151  }
152 
153  template <typename... Args>
154  static value_t
155  value(const labelset_t& ls, Args&&... args)
156  {
157  return ls.value(std::forward<Args>(args)...);
158  }
159 
160  ATTRIBUTE_PURE
161  static typename labelset_t::value_t
162  get_value(const value_t& v)
163  {
164  return v;
165  }
166  };
167  }
168 
170  template <typename LabelSet>
171  class nullableset : public LabelSet
172  {
173  public:
175  using labelset_ptr = std::shared_ptr<const labelset_t>;
178  using kind_t = typename helper_t::kind_t;
179 
180  using value_t = typename helper_t::value_t;
181  using word_t = typename labelset_t::word_t;
182 
184  : labelset_t{ls}, ls_{std::make_shared<const labelset_t>(ls)}
185  {}
186 
187  nullableset(const std::shared_ptr<const labelset_t>& ls)
188  : labelset_t{ls}, ls_{ls}
189  {}
190 
191  static std::string sname()
192  {
193  return "lan<" + labelset_t::sname() + ">";
194  }
195 
196  std::string vname(bool full = true) const
197  {
198  return "lan<" + labelset()->vname(full) + ">";
199  }
200 
202  static nullableset make(std::istream& i)
203  {
204  return helper_t::make(i);
205  }
206 
210  bool open(bool o) const
211  {
212  return this->labelset()->open(o);
213  }
214 
215  static constexpr bool
217  {
218  return true;
219  }
220 
221  static constexpr bool
223  {
224  return false;
225  }
226 
227  static constexpr bool
229  {
230  return labelset_t::is_letterized();
231  }
232 
233  static constexpr bool is_free()
234  {
235  return false;
236  }
237 
238  ATTRIBUTE_PURE
239  static constexpr value_t
240  one()
241  {
242  return helper_t::one();
243  }
244 
245  ATTRIBUTE_PURE
246  static bool
248  {
249  return helper_t::is_one(l);
250  }
251 
252  bool
253  is_valid(value_t v) const
254  {
255  return is_one(v) || labelset()->is_valid(get_value(v));
256  }
257 
258  value_t
260  {
261  return v;
262  }
263 
264  value_t
265  conv(oneset, typename oneset::value_t) const
266  {
267  return one();
268  }
269 
273  template <typename LabelSet_>
274  value_t
275  conv(const LabelSet_& ls, typename LabelSet_::value_t v) const
276  {
277  return value(labelset()->conv(ls, v));
278  }
279 
280  const labelset_ptr labelset() const
281  {
282  return ls_;
283  }
284 
285  template <typename... Args>
286  value_t
287  value(Args&&... args) const
288  {
289  return helper_t::value(*ls_, std::forward<Args>(args)...);
290  }
291 
292  word_t
293  word(const value_t& l) const
294  {
295  // FIXME: looks wrong: are sure to issue the empty word on one?
296  return labelset()->word(get_value(l));
297  }
298 
300  static bool equals(const value_t& l, const value_t& r)
301  {
302  if (is_one(l))
303  return is_one(r);
304  return !is_one(r) && labelset_t::equals(get_value(l), get_value(r));
305  }
306 
308  static bool less_than(const value_t& l, const value_t& r)
309  {
310  if (is_one(r))
311  return false;
312  else if (is_one(l))
313  return true;
315  get_value(r));
316  }
317 
318  static value_t
320  {
321  return helper_t::special();
322  }
323 
324  static bool
325  is_special(const value_t& v)
326  {
327  return !is_one(v) && labelset_t::is_special(get_value(v));
328  }
329 
330  size_t size(const value_t& v) const
331  {
332  return is_one(v) ? 0 : labelset_t::size(get_value(v));
333  }
334 
335  // FIXME: specialize for both implementation.
336  static size_t hash(const value_t& v)
337  {
338  std::size_t res = 0;
339  std::hash_combine(res, labelset_t::hash(get_value(v)));
340  std::hash_combine(res, helper_t::is_one(v));
341  return res;
342  }
343 
344  value_t
345  conv(std::istream& i) const
346  {
347  value_t res;
348  int c = i.peek();
349  if (c == '\\')
350  {
351  i.ignore();
352  c = i.get();
353  require(c == 'e', "invalid label: unexpected \\", str_escape(c));
354  res = one();
355  }
356  else
357  res = value(ls_->conv(i));
358  return res;
359  }
360 
361  std::set<value_t>
362  convs(std::istream& i) const
363  {
364  auto l = ls_->convs(i);
365  std::set<value_t> res;
366  for (auto v : l)
367  res.emplace(value(v));
368  return res;
369  }
370 
371  std::ostream&
372  print(value_t l, std::ostream& o,
373  symbol format = symbol{"text"}) const
374  {
375  if (is_one(l))
376  o << (format == "latex" ? "\\varepsilon" : "\\e");
377  else
378  labelset()->print(get_value(l), o, format);
379  return o;
380  }
381 
382  static void
383  make_nullableset_kind(std::istream& is)
384  {
385  eat(is, "lan");
386  }
387 
388  value_t
389  zero() const
390  {
391  return value(labelset()->zero());
392  }
393 
394  bool
395  is_zero(const value_t& v) const
396  {
397  return labelset()->is_zero(get_value(v));
398  }
399 
400  bool
401  is_letter(const value_t& v) const
402  {
403  return labelset()->is_letter(get_value(v));
404  }
405 
406  value_t
407  transpose(const value_t& l) const
408  {
409  if (is_one(l))
410  return l;
411  return value(ls_->transpose(get_value(l)));
412  }
413 
414  std::ostream&
415  print_set(std::ostream& o, symbol format = symbol{"text"}) const
416  {
417  if (format == "latex")
418  {
419  o << "(";
420  labelset()->print_set(o, format);
421  o << ")^?";
422  }
423  else if (format == "text")
424  o << vname(true);
425  else
426  raise("invalid format: ", format);
427  return o;
428  }
429 
431  static typename labelset_t::value_t
432  get_value(const value_t& v)
433  {
434  return helper_t::get_value(v);
435  }
436 
438  };
439 
440  namespace detail
441  {
443  template <typename LabelSet>
445  {
447  static type value(const nullableset<LabelSet>& ls)
448  {
449  return ls;
450  }
451  };
452 
454  template <typename LabelSet>
456  {
458  static type value(const nullableset<LabelSet>& ls)
459  {
460  return make_wordset(*ls.labelset());
461  }
462  };
463 
464  /*-------.
465  | Join. |
466  `-------*/
467 
469  template <typename LS>
470  struct join_impl<oneset, LS,
471  enable_if_t<!LS::has_one()>>
472  {
474  static type join(const oneset&, const LS& ls)
475  {
476  return {ls};
477  }
478  };
479 
481  template <typename LS>
482  struct join_impl<oneset, LS,
483  enable_if_t<LS::has_one()>>
484  {
485  using type = LS;
486  static type join(const oneset&, const LS& ls)
487  {
488  return ls;
489  }
490  };
491 
493  template <typename LS1, typename LS2>
494  struct join_impl<LS1, nullableset<LS2>>
495  {
497  static type join(const LS1& ls1, const nullableset<LS2>& ls2)
498  {
499  return {::vcsn::join(ls1, *ls2.labelset())};
500  }
501  };
502 
507  template <typename LS1, typename LS2>
508  struct join_impl<nullableset<LS1>, nullableset<LS2>>
509  {
511  static type join(const nullableset<LS1>& ls1, const nullableset<LS2>& ls2)
512  {
513  return {::vcsn::join(*ls1.labelset(), *ls2.labelset())};
514  }
515  };
516  }
517 
518  /*-------.
519  | Meet. |
520  `-------*/
521 
522 #define DEFINE(Lhs, Rhs, Res) \
523  template <typename GenSet> \
524  Res \
525  meet(const Lhs& lhs, const Rhs& rhs) \
526  { \
527  return {intersection(lhs.genset(), rhs.genset())}; \
528  }
529 
531  DEFINE(nullableset<letterset<GenSet>>,
533 
536 
539 
540  template <typename Lls, typename Rls>
542  meet(const nullableset<Lls>& lhs, const nullableset<Rls>& rhs)
543  {
544  return nullableset<meet_t<Lls, Rls>>{meet(*lhs.labelset(), *rhs.labelset())};
545  }
546 
547 #undef DEFINE
548 
549 }
550 
551 #endif // !VCSN_LABELSET_NULLABLESET_HH
value_t value(Args &&...args) const
Value constructor.
Definition: letterset.hh:86
std::ostream & print_set(std::ostream &o, symbol format=symbol{"text"}) const
Definition: nullableset.hh:415
typename LabelSet::kind_t kind_t
Definition: nullableset.hh:31
word_t word(const value_t &l) const
Definition: nullableset.hh:293
value_t zero() const
Definition: nullableset.hh:389
Add support for an empty word to a LabelSet that does not provide such special label to this end...
Definition: nullableset.hh:26
static type value(const nullableset< LabelSet > &ls)
Definition: nullableset.hh:447
bool is_valid(value_t v) const
Definition: nullableset.hh:253
value_t conv(oneset, typename oneset::value_t) const
Definition: nullableset.hh:265
std::ostream & print(value_t l, std::ostream &o, symbol format=symbol{"text"}) const
Definition: nullableset.hh:372
static type join(const nullableset< LS1 > &ls1, const nullableset< LS2 > &ls2)
Definition: nullableset.hh:511
static ATTRIBUTE_PURE labelset_t::value_t get_value(const value_t &v)
Definition: nullableset.hh:91
static std::string sname()
Definition: nullableset.hh:191
The LAW from a LAL.
Definition: labelset.hh:62
value_t transpose(const value_t &l) const
Definition: nullableset.hh:407
typename helper_t::kind_t kind_t
Definition: nullableset.hh:178
typename std::enable_if< Cond, T >::type enable_if_t
Definition: type_traits.hh:7
static bool is_special(const value_t &v)
Definition: nullableset.hh:325
std::string vname(bool full=true) const
Definition: nullableset.hh:196
static ATTRIBUTE_PURE bool is_one(value_t l)
Definition: nullableset.hh:77
Implementation of labels are nullables (letter or empty).
Definition: fwd.hh:13
static bool less_than(const value_t &l, const value_t &r)
Whether l < r.
Definition: nullableset.hh:308
boost::flyweight< std::string, boost::flyweights::no_tracking > symbol
An internalized string.
Definition: symbol.hh:24
std::string sname()
Definition: name.hh:31
typename helper_t::value_t value_t
Definition: nullableset.hh:180
std::ostream & str_escape(std::ostream &os, const std::string &str)
Output a string, escaping special characters.
Definition: escape.cc:43
static ATTRIBUTE_PURE constexpr null::value_t special()
Definition: nullableset.hh:134
std::pair< typename labelset_t::value_t, bool > value_t
Definition: nullableset.hh:30
Implementation of labels are ones: there is a single instance of label.
Definition: oneset.hh:18
static void make_nullableset_kind(std::istream &is)
Definition: nullableset.hh:383
const labelset_ptr labelset() const
Definition: nullableset.hh:280
static type join(const LS1 &ls1, const nullableset< LS2 > &ls2)
Definition: nullableset.hh:497
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:275
#define DEFINE(Lhs, Rhs, Res)
Definition: nullableset.hh:522
static ATTRIBUTE_PURE constexpr value_t one()
Definition: nullableset.hh:47
static value_t special()
Definition: nullableset.hh:319
value_t conv(std::istream &i) const
Definition: nullableset.hh:345
std::shared_ptr< const labelset_t > labelset_ptr
Definition: nullableset.hh:175
typename law_traits< LabelSet >::type law_t
The smallest wordset that includes LabelSet.
Definition: labelset.hh:67
static constexpr bool is_free()
Definition: nullableset.hh:233
size_t size(const value_t &v) const
Definition: nullableset.hh:330
static constexpr bool is_letterized()
Definition: nullableset.hh:228
law_t< LabelSet > make_wordset(const LabelSet &ls)
The wordset of a labelset.
Definition: labelset.hh:72
static value_t value(const labelset_t &ls, Args &&...args)
Definition: nullableset.hh:84
auto meet(const ratexpset< Ctx1 > &a, const ratexpset< Ctx2 > &b) -> ratexpset< meet_t< Ctx1, Ctx2 >>
The meet of two ratexpsets.
Definition: ratexpset.hh:480
letter_t value_t
Definition: letterset.hh:33
static size_t hash(const value_t &v)
Definition: nullableset.hh:336
std::istringstream is
The input stream: the specification to translate.
Definition: translate.cc:329
static ATTRIBUTE_PURE std::enable_if< Ls::has_one(), bool >::type is_one_(value_t l)
Definition: nullableset.hh:62
Empty labels, for LAO.
Definition: empty.hh:9
A structure that implements the computation of join(V1, V2).
Definition: join.hh:19
value_t conv(self_type, value_t v) const
Definition: nullableset.hh:259
static constexpr bool is_ratexpset()
Definition: nullableset.hh:222
static bool equals(const value_t &l, const value_t &r)
Whether l == r.
Definition: nullableset.hh:300
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:36
nullableset(const labelset_t &ls)
Definition: nullableset.hh:183
bool is_zero(const value_t &v) const
Definition: nullableset.hh:395
bool open(bool o) const
Whether unknown letters should be added, or rejected.
Definition: nullableset.hh:210
static nullableset make(std::istream &i)
Build from the description in is.
Definition: nullableset.hh:202
static type value(const nullableset< LabelSet > &ls)
Definition: nullableset.hh:458
static ATTRIBUTE_PURE labelset_t::value_t get_value(const value_t &v)
Definition: nullableset.hh:162
char eat(std::istream &is, char c)
Check lookahead character and advance.
Definition: stream.cc:37
labelset_ptr ls_
Definition: nullableset.hh:437
typename labelset_t::word_t word_t
Definition: nullableset.hh:181
static ATTRIBUTE_PURE bool is_one(value_t l)
Definition: nullableset.hh:247
bool is_letter(const value_t &v) const
Definition: nullableset.hh:401
Implementation of labels are letters.
Definition: fwd.hh:9
GenSet genset_t
Definition: letterset.hh:24
static value_t value(const labelset_t &ls, Args &&...args)
Definition: nullableset.hh:155
static ATTRIBUTE_PURE bool is_one(value_t l)
Definition: nullableset.hh:148
auto join(const ValueSet &vs) -> ValueSet
The join of a single valueset.
Definition: join.hh:44
static ATTRIBUTE_PURE constexpr value_t one()
Definition: nullableset.hh:240
static labelset_t::value_t get_value(const value_t &v)
Return the value when it's not one.
Definition: nullableset.hh:432
RatExpSet::value_t less_than(const RatExpSet &rs, const typename RatExpSet::value_t &v)
Definition: less-than.hh:150
static constexpr bool has_one()
Definition: nullableset.hh:216
static ATTRIBUTE_PURE constexpr value_t special()
Definition: nullableset.hh:54
std::set< value_t > convs(std::istream &i) const
Definition: nullableset.hh:362
nullableset(const std::shared_ptr< const labelset_t > &ls)
Definition: nullableset.hh:187
The smallest nullableset which includes LabelSet.
Definition: labelset.hh:22
static null make(std::istream &is)
Definition: nullableset.hh:33
value_t value(Args &&...args) const
Definition: nullableset.hh:287
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:39
static ATTRIBUTE_PURE constexpr null::value_t one()
Definition: nullableset.hh:141
static ATTRIBUTE_PURE std::enable_if<!Ls::has_one(), bool >::type is_one_(value_t l)
Definition: nullableset.hh:70