Vcsn  2.1
Be Rational
wordset.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <memory>
4 #include <set>
5 
6 #include <boost/range/algorithm/mismatch.hpp>
7 #include <boost/algorithm/string/predicate.hpp> // starts_with
8 
9 #include <vcsn/core/kind.hh>
10 #include <vcsn/labelset/fwd.hh>
12 #include <vcsn/labelset/letterset.hh> // for letterized_traits
14 #include <vcsn/misc/attributes.hh>
15 #include <vcsn/misc/functional.hh>
16 #include <vcsn/misc/raise.hh>
17 
18 namespace vcsn
19 {
21  template <typename GenSet>
22  class wordset: public detail::genset_labelset<GenSet>
23  {
24  public:
25  using genset_t = GenSet;
27  using self_t = wordset;
28  using genset_ptr = std::shared_ptr<const genset_t>;
29 
30  using letter_t = typename genset_t::letter_t;
31  using word_t = typename genset_t::word_t;
32  using letters_t = std::set<letter_t>;
33 
34  using value_t = word_t;
35 
37 
38  wordset(const genset_ptr& gs)
39  : super_t{gs}
40  {}
41 
42  wordset(const genset_t& gs = {})
43  : wordset{std::make_shared<const genset_t>(gs)}
44  {}
45 
46  wordset(const std::initializer_list<letter_t>& letters)
47  : wordset(std::make_shared<const genset_t>(letters))
48  {}
49 
50  static symbol sname()
51  {
52  static symbol res("wordset<" + super_t::sname() + '>');
53  return res;
54  }
55 
57  static wordset make(std::istream& is)
58  {
59  // name: wordset<char_letters(abc)>.
60  // ^^^^^^^ ^^^^^^^^^^^^^^^^^
61  // kind genset
62  eat(is, "wordset<");
63  auto gs = genset_t::make(is);
64  eat(is, '>');
65  return gs;
66  }
67 
71  bool open(bool o) const
72  {
73  return this->genset().open(o);
74  }
75 
76  static constexpr bool is_free()
77  {
78  return false;
79  }
80 
82  template <typename... Args>
83  value_t value(Args&&... args) const
84  {
85  return value_t{std::forward<Args>(args)...};
86  }
87 
89  word_t word(const value_t& v) const
90  {
91  return v;
92  }
93 
95  static word_t
97  {
98  return v;
99  }
100 
103  static word_t
105  {
106  return v;
107  }
108 
110  static bool
111  equal(const value_t& l, const value_t& r)
112  {
113  return l == r;
114  }
115 
117  static bool less(const value_t& l, const value_t& r)
118  {
119  // Be sure to use genset::less().
120  auto s1 = l.size();
121  auto s2 = r.size();
122  if (s1 < s2)
123  return true;
124  else if (s2 < s1)
125  return false;
126  else
127  return genset_t::less(l, r);
128  }
129 
130  static value_t
132  {
133  return genset_t::template special<value_t>();
134  }
135 
136  static bool
138  {
139  return v == special();
140  }
141 
142  bool
143  is_valid(const value_t& v) const
144  {
145  for (auto l: v)
146  if (!this->has(l))
147  return false;
148  return true;
149  }
150 
151  static constexpr bool
153  {
154  return false;
155  }
156 
157  static constexpr bool
159  {
160  return true;
161  }
162 
163  static constexpr bool
165  {
166  return false;
167  }
168 
169  static value_t
170  one()
171  {
172  return genset_t::empty_word();
173  }
174 
175  static bool
176  is_one(const value_t& l) ATTRIBUTE_PURE
177  {
178  return genset_t::is_empty_word(l);
179  }
180 
181  static size_t size(const value_t& v)
182  {
183  // Not v.length(), because word_t can actually be a vector
184  // (e.g., with string_letters).
185  return v.size();
186  }
187 
188  static size_t hash(const value_t& v)
189  {
190  return hash_value(v);
191  }
192 
193  value_t
194  conv(self_t, const value_t& v) const
195  {
196  return v;
197  }
198 
199  template <typename GenSet_>
200  value_t
202  typename letterset<GenSet_>::value_t v) const
203  {
204  if (ls.is_special(v))
205  return special();
206  else
207  {
208  auto res = value(v);
209  require(is_valid(res),
210  *this, ": conv: invalid label: ", str_escape(v));
211  return res;
212  }
213  }
214 
215  template <typename LabelSet_>
216  value_t
218  const typename nullableset<LabelSet_>::value_t& v) const
219  {
220  if (ls.is_one(v))
221  return one();
222  else
223  return conv(*ls.labelset(), ls.get_value(v));
224  }
225 
226  value_t
227  conv(std::istream& i, bool = true) const
228  {
229  return this->genset().get_word(i);
230  }
231 
238  template <typename Fun>
239  void convs(std::istream& i, Fun fun) const
240  {
241  this->convs_(i, [this,fun](letter_t l) { fun(value(l)); });
242  }
243 
244  std::ostream&
245  print(const value_t& l, std::ostream& o,
246  format fmt = {}) const
247  {
248  if (is_one(l))
249  o << (fmt == format::latex ? "\\varepsilon" : "\\e");
250  else if (!is_special(l))
251  this->genset().print(l, o, fmt);
252  return o;
253  }
254 
255  std::ostream&
256  print_set(std::ostream& o, format fmt = {}) const
257  {
258  if (fmt == format::latex)
259  {
260  this->genset().print_set(o, fmt);
261  o << "^*";
262  }
263  else if (fmt == format::text)
264  {
265  o << "wordset<";
266  this->genset().print_set(o, fmt);
267  o << '>';
268  }
269  else
270  raise(*this, ": print_set: invalid format: ", fmt);
271  return o;
272  }
273 
275  static value_t lgcd(const value_t& w1, const value_t& w2)
276  {
277  return {w1.begin(), boost::mismatch(w1, w2).first};
278  }
279 
282  static value_t ldiv(const value_t& w1, const value_t& w2)
283  {
284  using boost::algorithm::starts_with;
285  require(starts_with(w2, w1),
286  sname(), ": ldiv: invalid arguments: ", str_escape(w1),
287  ", ", str_escape(w2));
288  return w2.substr(size(w1));
289  }
290 
292  static value_t& ldiv_here(const value_t& w1, value_t& w2)
293  {
294  w2 = ldiv(w1, w2);
295  return w2;
296  }
297  };
298 
299  namespace detail
300  {
302  template <typename GenSet>
303  struct letterized_traits<wordset<GenSet>>
304  {
305  static constexpr bool is_letterized = false;
306 
307  using labelset_t = nullableset<letterset<GenSet>>;
308 
309  static labelset_t labelset(const wordset<GenSet>& ls)
310  {
311  return {ls.genset()};
312  }
313  };
314 
316  template <typename GenSet>
317  struct nullableset_traits<wordset<GenSet>>
318  {
319  using type = wordset<GenSet>;
320  static type value(const wordset<GenSet>& ls)
321  {
322  return ls;
323  }
324  };
325 
326  template <typename GenSet>
327  struct law_traits<wordset<GenSet>>
328  {
329  using type = wordset<GenSet>;
330  static type value(const wordset<GenSet>& ls)
331  {
332  return ls;
333  }
334  };
335 
336  /*-------.
337  | Join. |
338  `-------*/
339 
341 #define DEFINE(Lhs, Rhs) \
342  template <typename GenSet> \
343  struct join_impl<Lhs, Rhs> \
344  { \
345  using type = Rhs; \
346  static type join(const Lhs& lhs, const Rhs& rhs) \
347  { \
348  return {get_union(lhs.genset(), rhs.genset())}; \
349  } \
350  }
351 
353  DEFINE(letterset<GenSet>, wordset<GenSet>);
354  DEFINE(nullableset<letterset<GenSet>>, wordset<GenSet>);
355  DEFINE(wordset<GenSet>, wordset<GenSet>);
356 #undef DEFINE
357  }
358 
360  // FIXME: Factor in genset_labelset?
361  template <typename GenSet>
362  wordset<GenSet>
363  meet(const wordset<GenSet>& lhs, const wordset<GenSet>& rhs)
364  {
365  return {intersection(lhs.genset(), rhs.genset())};
366  }
367 }
STL namespace.
static bool is_one(const value_t &l) ATTRIBUTE_PURE
Definition: wordset.hh:176
static word_t letters_of_padded(const value_t &v, letter_t)
Prepare to iterate over the letters of v.
Definition: wordset.hh:104
std::ostream & str_escape(std::ostream &os, const std::string &str)
Output a string, escaping special characters.
Definition: escape.cc:43
Implementation of labels are letters.
Definition: fwd.hh:10
word_t word(const value_t &v) const
Convert to a word.
Definition: wordset.hh:89
weightset_mixin< detail::r_impl > r
Definition: fwd.hh:54
This class has no modeling purpose, it only serves to factor code common to letterset, nullableset and wordset.
static constexpr bool has_one()
Definition: wordset.hh:158
ATTRIBUTE_PURE auto has(Args &&...args) const -> decltype(this->genset().has(std::forward< Args >(args)...))
typename genset_t::letters_t letters_t
wordset(const std::initializer_list< letter_t > &letters)
Definition: wordset.hh:46
typename helper_t::value_t value_t
Definition: nullableset.hh:166
std::istringstream is
The input stream: the specification to translate.
Definition: translate.cc:372
char eat(std::istream &is, char c)
Check lookahead character and advance.
Definition: stream.cc:37
static size_t hash(const value_t &v)
Definition: wordset.hh:188
value_t conv(std::istream &i, bool=true) const
Definition: wordset.hh:227
bool open(bool o) const
Whether unknown letters should be added, or rejected.
Definition: wordset.hh:71
std::shared_ptr< const genset_t > genset_ptr
std::ostream & print_set(std::ostream &o, format fmt={}) const
Definition: wordset.hh:256
wordset(const genset_t &gs={})
Definition: wordset.hh:42
auto hash_value(const T &v) -> decltype(std::hash< T >
Following the naming convention of Boost.
Definition: functional.hh:63
typename genset_t::word_t word_t
Definition: wordset.hh:31
static bool is_special(const value_t &v)
Definition: wordset.hh:137
value_t value(Args &&...args) const
Value constructor.
Definition: wordset.hh:83
value_t conv(const nullableset< LabelSet_ > &ls, const typename nullableset< LabelSet_ >::value_t &v) const
Definition: wordset.hh:217
const genset_t & genset() const
An input/output format.
Definition: format.hh:11
static ATTRIBUTE_PURE bool is_one(value_t l)
Definition: nullableset.hh:242
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
static bool equal(const value_t &l, const value_t &r)
Whether l == r.
Definition: wordset.hh:111
static bool is_special(value_t v) ATTRIBUTE_PURE
Definition: letterset.hh:162
static constexpr bool is_expressionset()
Definition: wordset.hh:152
void convs(std::istream &i, Fun fun) const
Process a range of labels.
Definition: wordset.hh:239
static constexpr bool is_free()
Definition: wordset.hh:76
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:75
const labelset_ptr labelset() const
Definition: nullableset.hh:283
static symbol sname()
Definition: wordset.hh:50
static value_t one()
Definition: wordset.hh:170
word_t value_t
Definition: wordset.hh:34
value_t conv(self_t, const value_t &v) const
Definition: wordset.hh:194
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Definition: symbol.hh:23
static size_t size(const value_t &v)
Definition: wordset.hh:181
static bool less(const value_t &l, const value_t &r)
Whether l < r.
Definition: wordset.hh:117
value_t conv(const letterset< GenSet_ > &ls, typename letterset< GenSet_ >::value_t v) const
Definition: wordset.hh:201
bool is_valid(const value_t &v) const
Definition: wordset.hh:143
static constexpr bool is_letterized()
Definition: wordset.hh:164
wordset(const genset_ptr &gs)
Definition: wordset.hh:38
std::ostream & print(const value_t &l, std::ostream &o, format fmt={}) const
Definition: wordset.hh:245
letter_t value_t
Definition: letterset.hh:32
static wordset make(std::istream &is)
Build from the description in is.
Definition: wordset.hh:57
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
typename genset_t::letter_t letter_t
static word_t letters_of(const value_t &v)
Prepare to iterate over the letters of v.
Definition: wordset.hh:96
static value_t special()
Definition: wordset.hh:131
Implementation of labels are words.
Definition: fwd.hh:31
void convs_(std::istream &i, Fun fun) const
Read and process a class of letters.
Implementation of labels are nullables (letter or empty).
Definition: fwd.hh:14