Vcsn  2.1
Be Rational
labelset.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <boost/range/algorithm/find.hpp>
4 #include <boost/range/algorithm/find_if.hpp>
5 #include <boost/range/algorithm_ext/is_sorted.hpp>
6 
7 #include <vcsn/ctx/context.hh>
8 #include <vcsn/ctx/traits.hh> // labelset_t_of
9 #include <vcsn/misc/algorithm.hh> // none_of
10 #include <vcsn/misc/functional.hh> // less
11 #include <vcsn/misc/type_traits.hh> // detect
12 
13 namespace vcsn
14 {
15  namespace detail
16  {
17  template <typename LabelSet>
18  using genset_t = decltype(std::declval<LabelSet>().genset());
19 
20  template <typename LabelSet>
22 
23 
24  /*-----------.
25  | has_one. |
26  `-----------*/
27 
28  template <typename LabelSet>
29  using one_t = decltype(std::declval<LabelSet>().one());
30 
31  template <typename LabelSet>
33 
34 
35  /*-------------.
36  | label_one. |
37  `-------------*/
38 
40  template <typename LabelSet>
41  auto label_one()
42  -> enable_if_t<LabelSet::has_one(),
43  typename LabelSet::value_t>
44  {
45  return LabelSet::one();
46  }
47 
48  template <typename LabelSet>
49  ATTRIBUTE_NORETURN
50  auto label_one()
51  -> enable_if_t<!LabelSet::has_one(),
52  typename LabelSet::value_t>
53  {
54  raise(LabelSet::sname(), ": does not feature a neutral");
55  }
56 
57 #if defined __GNUC__ && !defined __clang__
58  // GCC can't figure out that this one does return, because of the template
59  // instanciation, where one of them doesn't return.
60 # pragma GCC diagnostic push
61 # pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn"
62 #endif
63 
65  template <typename LabelSet>
66  auto label_one(const LabelSet&)
67  -> typename LabelSet::value_t
68  {
69  return label_one<LabelSet>();
70  }
71 
72 #if defined __GNUC__ && !defined __clang__
73 # pragma GCC diagnostic pop
74 #endif
75 
76  /*-------------------.
77  | make_letterized. |
78  `-------------------*/
79 
80  template <typename LabelSet>
82  {
83  static constexpr bool is_letterized = true;
84 
85  using labelset_t = LabelSet;
86  static labelset_t labelset(const labelset_t& ls)
87  {
88  return std::make_shared<labelset_t>(labelset_t{ls.genset()});
89  }
90  };
91 
92  template <typename LabelSet>
93  using letterized_t =
95 
96  template <typename LabelSet>
97  using is_letterized_t =
99 
100  template <typename LabelSet>
102  make_letterized(const LabelSet& ls)
103  {
105  }
106 
107 
108  /*---------------------------.
109  | make_letterized_context. |
110  `---------------------------*/
111 
112  template <typename Context>
113  using letterized_context =
116 
118  template <typename LabelSet, typename WeightSet>
121  {
122  return {make_letterized(*c.labelset()), *c.weightset()};
123  }
124 
125 
126  /*--------------------.
127  | make_nullableset. |
128  `--------------------*/
129 
138  template <typename LabelSet,
139  typename Enable = void>
141  {};
142 
144  template <typename LabelSet>
146 
148  template <typename LabelSet>
150  make_nullableset(const LabelSet& ls)
151  {
153  };
154 
155  /*----------------------------.
156  | make_nullableset_context. |
157  `----------------------------*/
158 
159  template <typename Ctx>
162 
164  template <typename LabelSet, typename WeightSet>
167  {
168  return {make_nullableset(*ctx.labelset()), *ctx.weightset()};
169  }
170 
171 
172  /*---------------.
173  | make_proper. |
174  `---------------*/
175 
183  template <typename LabelSet>
185  {
186  using type = LabelSet;
187  static type value(const LabelSet& ls)
188  {
189  return ls;
190  }
191  };
192 
194  template <typename LabelSet>
196 
198  template <typename LabelSet>
200  make_proper(const LabelSet& ls)
201  {
203  }
204 
205 
206  /*-----------------------.
207  | make_proper_context. |
208  `-----------------------*/
209 
210  template <typename Context>
211  using proper_context =
214 
216  template <typename LabelSet, typename WeightSet>
217  auto
220  {
221  return {make_proper(*ctx.labelset()), *ctx.weightset()};
222  }
223 
224 
225  /*---------------------.
226  | make_free_context. |
227  `---------------------*/
228 
229  template <typename Context>
230  using free_context =
233 
235  template <typename LabelSet, typename WeightSet>
238  {
239  return {make_proper(make_letterized(*c.labelset())), *c.weightset()};
240  }
241 
242 
243  /*---------------.
244  | make_wordset. |
245  `---------------*/
246 
250  template <typename ValueSet>
251  struct law_traits
252  {};
253 
255  template <typename LabelSet>
257 
259  template <typename LabelSet>
260  inline law_t<LabelSet>
261  make_wordset(const LabelSet& ls)
262  {
263  return law_traits<LabelSet>::value(ls);
264  };
265 
266  /*--------------------.
267  | make_word_context. |
268  `--------------------*/
269 
270  template <typename Ctx>
271  using word_context_t
272  = context<law_t<labelset_t_of<Ctx>>, weightset_t_of<Ctx>>;
273 
275  template <typename LabelSet, typename WeightSet>
278  {
279  return {make_wordset(*ctx.labelset()), *ctx.weightset()};
280  }
281 
282 
283  /*---------------------.
284  | print_label_class. |
285  `---------------------*/
286 
291  template <typename LabelSet>
292  std::ostream&
293  print_label_ranges_(const LabelSet& ls,
294  const std::vector<typename LabelSet::value_t>& letters,
295  const std::vector<typename LabelSet::value_t>& alphabet,
296  std::ostream& out,
297  format fmt)
298  {
299  for (auto it = std::begin(letters), letters_end = std::end(letters);
300  it != letters_end; ++it)
301  {
302  auto end
303  // not std::mismatch, to please G++ 4.8.
304  = vcsn::detail::mismatch(it, letters_end,
305  boost::range::find(alphabet, *it),
306  alphabet.end()).first;
307  ls.print(*it, out, fmt);
308  // No range for two letters or less.
309  auto width = std::distance(it, end);
310  if (2 < width)
311  {
312  it += width - 1;
313  // Using `-` in LaTeX math mode means minus (wow, 4
314  // m-words in a row), which results in a long dash, and
315  // too much space around it.
316  out << (fmt == format::latex ? "\\textrm{-}" : "-");
317  ls.print(*it, out, fmt);
318  }
319  }
320  return out;
321  }
322 
327  template <typename LabelSet>
328  std::ostream&
329  print_label_class(const LabelSet& ls,
330  const std::vector<typename LabelSet::value_t>& letters,
331  std::ostream& out,
332  format fmt)
333  {
334  using letters_t = std::vector<typename LabelSet::value_t>;
335  // In alphabetical order.
336  auto alphabet = letters_t{};
337  for (auto l : ls.genset())
338  alphabet.emplace_back(ls.value(l));
339 
340  out << '[';
341  // If the letters are strictly increasing (hence using
342  // less_equal, not just less), and are many compared to the
343  // alphabet (say, at least two thirds), then we should probably
344  // use negated classes instead.
345  if (boost::is_sorted(letters, vcsn::less_equal<LabelSet>{})
346  && 2 * boost::distance(alphabet) < 3 * boost::distance(letters))
347  {
348  // FIXME: we can certainly do better and avoid the
349  // construction of this vector.
350  auto negated = letters_t{};
351  for (auto l: alphabet)
352  if (none_of_equal(letters, l))
353  negated.emplace_back(l);
354  out << (fmt == format::latex ? "\\hat{}" : "^");
355  print_label_ranges_(ls, negated, alphabet, out, fmt);
356  }
357  else
358  print_label_ranges_(ls, letters, alphabet, out, fmt);
359  out << ']';
360 
361  return out;
362  }
363  }
364 }
bool_constant< letterized_traits< LabelSet >::is_letterized > is_letterized_t
Definition: labelset.hh:98
std::ostream & print_label_class(const LabelSet &ls, const std::vector< typename LabelSet::value_t > &letters, std::ostream &out, format fmt)
Print a set of labels (letterized) with classes.
Definition: labelset.hh:329
typename proper_traits< LabelSet >::type proper_t
The type of the corresponding proper LabelSet.
Definition: labelset.hh:195
nullableset_context_t< context< LabelSet, WeightSet > > make_nullableset_context(const context< LabelSet, WeightSet > &ctx)
The nullableset context of a context.
Definition: labelset.hh:166
auto label_one() -> enable_if_t< LabelSet::has_one(), typename LabelSet::value_t >
This LabelSet's one(), if supported.
Definition: labelset.hh:41
word_context_t< context< LabelSet, WeightSet > > make_word_context(const context< LabelSet, WeightSet > &ctx)
The wordset context of a context.
Definition: labelset.hh:277
letterized_t< LabelSet > make_letterized(const LabelSet &ls)
Definition: labelset.hh:102
static labelset_t labelset(const labelset_t &ls)
Definition: labelset.hh:86
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
Definition: traits.hh:51
typename std::enable_if< Cond, T >::type enable_if_t
Definition: type_traits.hh:16
std::pair< InputIt1, InputIt2 > mismatch(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
Same as C++14's mismatch, which is not available in G++-4.8 with -std=c++1y.
Definition: algorithm.hh:132
std::ostream & print_label_ranges_(const LabelSet &ls, const std::vector< typename LabelSet::value_t > &letters, const std::vector< typename LabelSet::value_t > &alphabet, std::ostream &out, format fmt)
Print a set of labels with ranges.
Definition: labelset.hh:293
auto make_proper_context(const context< LabelSet, WeightSet > &ctx) -> proper_context< context< LabelSet, WeightSet >>
From a context, its non-nullable context.
Definition: labelset.hh:218
decltype(std::declval< LabelSet >().one()) one_t
Definition: labelset.hh:29
typename nullableset_traits< LabelSet >::type nullableset_t
The smallest nullableset that includes LabelSet.
Definition: labelset.hh:145
static dyn::context ctx(const driver &d)
Get the context of the driver.
Definition: parse.cc:80
context< letterized_t< labelset_t_of< Context >>, weightset_t_of< Context >> letterized_context
Definition: labelset.hh:115
An input/output format.
Definition: format.hh:11
const weightset_ptr & weightset() const
Definition: context.hh:100
static constexpr bool is_letterized
Definition: labelset.hh:83
bool none_of_equal(const Range &r, const Value &value)
Definition: algorithm.hh:156
From a labelset, its non-nullable labelset.
Definition: labelset.hh:184
proper_t< LabelSet > make_proper(const LabelSet &ls)
The corresponding proper LabelSet.
Definition: labelset.hh:200
law_t< LabelSet > make_wordset(const LabelSet &ls)
The wordset of a labelset.
Definition: labelset.hh:261
free_context< context< LabelSet, WeightSet > > make_free_context(const context< LabelSet, WeightSet > &c)
The free context for c.
Definition: labelset.hh:237
context< nullableset_t< labelset_t_of< Ctx >>, weightset_t_of< Ctx >> nullableset_context_t
Definition: labelset.hh:161
decltype(std::declval< LabelSet >().genset()) genset_t
Definition: labelset.hh:18
symbol sname()
Definition: name.hh:67
typename law_traits< LabelSet >::type law_t
The smallest wordset that includes LabelSet.
Definition: labelset.hh:256
The smallest nullableset which includes LabelSet.
Definition: labelset.hh:140
const labelset_ptr & labelset() const
Definition: context.hh:95
Functor to compare Values of ValueSets.
Definition: functional.hh:85
context< proper_t< letterized_t< labelset_t_of< Context >>>, weightset_t_of< Context >> free_context
Definition: labelset.hh:232
context< proper_t< labelset_t_of< Context >>, weightset_t_of< Context >> proper_context
Definition: labelset.hh:213
nullableset_t< LabelSet > make_nullableset(const LabelSet &ls)
The nullableset of a labelset.
Definition: labelset.hh:150
static type value(const LabelSet &ls)
Definition: labelset.hh:187
letterized_context< context< LabelSet, WeightSet > > make_letterized_context(const context< LabelSet, WeightSet > &c)
The letterized context for c.
Definition: labelset.hh:120
std::integral_constant< bool, B > bool_constant
Definition: type_traits.hh:35
constant< type_t::one, Context > one
Definition: fwd.hh:111
typename letterized_traits< LabelSet >::labelset_t letterized_t
Definition: labelset.hh:94
context< law_t< labelset_t_of< Ctx >>, weightset_t_of< Ctx >> word_context_t
Definition: labelset.hh:272
The LAW from a LAL.
Definition: labelset.hh:251