Vcsn  2.4
Be Rational
printer.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <iostream>
4 
5 #include <vcsn/algos/project.hh> // bad layering: should not be in algos.
8 #include <vcsn/ctx/traits.hh>
9 #include <vcsn/labelset/labelset.hh> // has_generators_mem_fn
10 #include <vcsn/misc/algorithm.hh> // initial_range
11 #include <vcsn/misc/attributes.hh>
12 #include <vcsn/misc/builtins.hh>
13 #include <vcsn/misc/cast.hh>
14 #include <vcsn/misc/format.hh>
15 #include <vcsn/misc/static-if.hh>
16 
17 namespace vcsn
18 {
19  namespace rat
20  {
34  enum class precedence_t
35  {
36  add,
37  compose,
38  tuple,
39  products,
40  shuffle = products,
43  ldivide,
44  mul,
45  word = mul, // Multi-letter atoms.
46  lweight,
47  rweight,
48  unary, // All the unary (postfix) operators.
49  star = unary,
50  complement = unary,
52  exponent = unary,
53  zero,
54  one,
55  atom,
56  };
57 
59  constexpr static const char* const superscripts[] =
60  {
61  "⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹"
62  };
63 
65  template <typename ExpSet>
66  class printer
67  : public ExpSet::const_visitor
68  {
69  public:
70  using expressionset_t = ExpSet;
71  using super_t = typename expressionset_t::const_visitor;
72  using self_t = printer;
73 
75  using identities_t = typename expressionset_t::identities_t;
79 
81  using node_t = typename super_t::node_t;
83  using value_t = typename node_t::value_t;
84  using inner_t = typename super_t::inner_t;
85  template <type_t Type>
86  using unary_t = typename super_t::template unary_t<Type>;
87  template <type_t Type>
88  using variadic_t = typename super_t::template variadic_t<Type>;
89  using leaf_t = typename super_t::leaf_t;
90 
92  constexpr static const char* me() { return "print"; }
93 
95  printer(const expressionset_t& rs, std::ostream& out);
96 
98  void format(format fmt);
99 
101  std::ostream&
103  {
104  return print_(*v);
105  }
106 
110  void print_child(const node_t& child, precedence_t parent);
111 
112  private:
114  std::ostream& print_(const node_t& v);
115 
117  void print_(const weight_t& w)
118  {
119  rs_.weightset()->print(w, out_, fmt_.for_weights());
120  }
121 
129  VCSN_RAT_VISIT(one, v);
130  VCSN_RAT_VISIT(mul, v);
137 
138  using tuple_t = typename super_t::tuple_t;
139 
140  template <typename Dummy = void>
141  struct visit_tuple
142  {
144  template <size_t I>
145  void print_(const tuple_t& v)
146  {
147  if (I)
149  auto rs = detail::project<I>(self_.rs_);
150  auto print = make_printer(rs, self_.out_);
151  print.format(self_.fmt_);
152  print.print_child(*std::get<I>(v.sub()), precedence_t::tuple);
153  }
154 
156  template <size_t... I>
158  {
159  using swallow = int[];
160  (void) swallow
161  {
162  (print_<I>(v),
163  0)...
164  };
165  }
166 
168  void operator()(const tuple_t& v)
169  {
171  print_(v, labelset_t::indices);
173  }
174  const self_t& self_;
175  };
176 
177  void visit(const tuple_t& v, std::true_type) override
178  {
179  detail::static_if<context_t::is_lat>
180  ([this](auto&& v){ visit_tuple<decltype(v)>{*this}(v); })
181  (v);
182  }
183 
184 
189  bool is_letter_(const node_t& v) const
190  {
191  auto atom = dynamic_cast<const atom_t*>(&v);
192  return atom && rs_.labelset()->is_letter(atom->value());
193  }
194 
209  bool is_word_(const node_t& v) const
210  {
211  auto atom = dynamic_cast<const atom_t*>(&v);
212  return (atom
213  && (context_t::is_lat
214  || ! rs_.labelset()->is_letter(atom->value())));
215  }
216 
221  bool is_braced_(const node_t& v) const
222  {
223  if (auto s = dynamic_cast<const add_t*>(&v))
224  {
225  auto range = letter_range(s->begin(), s->end());
226  return (end(range) == s->end()
227  && 3 < boost::distance(range));
228  }
229  else
230  return false;
231  }
232 
234  precedence_t precedence_(const node_t& v) const;
235 
237  void print_child_(const node_t& child, const node_t& parent);
238 
240  template <rat::exp::type_t Type>
241  void print_(const unary_t<Type>& n, const char* op);
242 
244  template <rat::exp::type_t Type>
245  void print_(const variadic_t<Type>& n, const char* op);
246 
248  ATTRIBUTE_PURE
249  bool shows_left_weight_(const node_t& n)
250  {
251  return n.type() == rat::type_t::lweight;
252  }
253 
256  template <typename Iterator>
257  auto letter_range(Iterator i, Iterator end) const
258  -> boost::iterator_range<Iterator>
259  {
261  (i, end,
262  [this](const value_t& c) { return is_letter_(*c); },
263  [this](const value_t& lhs, const value_t& rhs)
264  {
265  auto l = std::dynamic_pointer_cast<const atom_t>(lhs)->value();
266  auto r = std::dynamic_pointer_cast<const atom_t>(rhs)->value();
267  const auto& ls = *rs_.labelset();
268  // Require strictly increasing order.
269  return ls.less(l, r) || ls.equal(l, r);
270  });
271  }
272 
274  template <typename LS = labelset_t>
275  auto print_add_(const add_t& v)
276  -> std::enable_if_t<detail::has_generators_mem_fn<LS>{}, void>
277  {
278  bool first = true;
279  // Use classes for sums of letters.
280  for (auto i = std::begin(v), end = std::end(v);
281  i != end;
282  /* nothing. */)
283  {
284  if (! first)
285  out_ << add_;
286  first = false;
287  // If in front of a row of letters, in strictly increasing
288  // order, issue a class.
289  auto r = letter_range(i, end);
290  if (3 < distance(r))
291  {
292  // Gather the letters.
293  auto letters = std::vector<label_t>{};
294  for (/* nothing. */; i != r.end(); ++i)
295  letters
296  .emplace_back(down_pointer_cast<const atom_t>(*i)->value());
297  vcsn::detail::print_label_class(*rs_.labelset(), letters,
298  out_, fmt_);
299  }
300  else
301  {
302  // Otherwise, just print the child.
303  print_child_(**i, v);
304  ++i;
305  }
306  }
307  }
308 
310  template <typename LS = labelset_t>
311  auto print_add_(const add_t& v)
312  -> std::enable_if_t<!detail::has_generators_mem_fn<LS>{}, void>
313  {
314  print_(v, add_);
315  }
316 
318  std::ostream& out_;
320  class format fmt_;
324  const bool debug_ = !!getenv("VCSN_PARENS");
325 
330  const char* lgroup_ = nullptr;
331  const char* rgroup_ = nullptr;
333  const char* langle_ = nullptr;
334  const char* rangle_ = nullptr;
336  const char* lparen_ = nullptr;
337  const char* rparen_ = nullptr;
339  const char* lexponent_ = nullptr;
340  const char* rexponent_ = nullptr;
342  const char* lweight_ = nullptr;
343  const char* rweight_ = nullptr;
345  const char* ldivide_ = nullptr;
347  const char* star_ = nullptr;
348  const char* complement_ = nullptr;
350  const char* compose_ = nullptr;
351  const char* transposition_ = nullptr;
352  const char* conjunction_ = nullptr;
353  const char* infiltrate_ = nullptr;
354  const char* shuffle_ = nullptr;
355  const char* product_ = nullptr;
356  const char* add_ = nullptr;
357 
359  const char* tuple_left = nullptr;
361  const char* tuple_middle = nullptr;
363  const char* tuple_right = nullptr;
364 
366  const char* zero_ = nullptr;
367  const char* one_ = nullptr;
368  unsigned int exponent_threshold_ = 0;
369  };
370 
371  template <typename ExpSet>
373  make_printer(const ExpSet& rs, std::ostream& out)
374  {
375  return {rs, out};
376  }
377  } // namespace rat
378 } // namespace vcsn
379 
380 #include <vcsn/core/rat/printer.hxx>
std::ostream & print_(const node_t &v)
Print v.
Definition: printer.hxx:52
std::ostream & out_
Output stream.
Definition: printer.hh:318
const char * rexponent_
Definition: printer.hh:340
void print_(const tuple_t &v, detail::index_sequence< I... >)
Print all the tapes.
Definition: printer.hh:157
void print_(const weight_t &w)
Print a weight.
Definition: printer.hh:117
VCSN_RAT_VISIT(complement, v)
Definition: printer.hh:124
VCSN_RAT_VISIT(atom, v)
typename super_t::node_t node_t
Actual node, without indirection.
Definition: printer.hh:81
const char * rgroup_
Definition: printer.hh:331
const char * conjunction_
Definition: printer.hh:352
class format fmt_
Output format.
Definition: printer.hh:320
auto rs
Definition: lift.hh:152
const char * langle_
Left and right angle brackets for weights.
Definition: printer.hh:333
VCSN_RAT_VISIT(transposition, v)
Definition: printer.hh:135
void visit(const tuple_t &v, std::true_type) override
Specific handling to using exponents as syntactic sugar.
Definition: printer.hh:177
bool is_braced_(const node_t &v) const
Whether is naturally braced.
Definition: printer.hh:221
const expressionset_t & rs_
The expressionset.
Definition: printer.hh:322
An inner node implementing a weight.
Definition: expression.hh:255
Pretty-printer for rational expressions.
Definition: fwd.hh:28
const char * transposition_
Definition: printer.hh:351
const char * product_
Definition: printer.hh:355
static constexpr const char * me()
Name of this algorithm, for error messages.
Definition: printer.hh:92
context_t_of< expressionset_t > context_t
Definition: printer.hh:74
typename super_t::inner_t inner_t
Definition: printer.hh:84
const char * rweight_
Definition: printer.hh:343
weight_t_of< context_t > weight_t
Definition: printer.hh:78
An input/output format for valuesets.
Definition: format.hh:13
ExpSet expressionset_t
Definition: printer.hh:70
const char * rparen_
Definition: printer.hh:337
typename super_t::template unary_t< Type > unary_t
Definition: printer.hh:86
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
const char * tuple_left
Left tuple delimiter.
Definition: printer.hh:359
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
Definition: traits.hh:62
void print_child_(const node_t &child, const node_t &parent)
Print a child node, given its parent.
Definition: printer.hxx:302
void operator()(const tuple_t &v)
Entry point.
Definition: printer.hh:168
void print_(const tuple_t &v)
Print one tape.
Definition: printer.hh:145
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
Definition: traits.hh:63
const char * tuple_middle
Tuple tape separator.
Definition: printer.hh:361
typename expressionset_t::const_visitor super_t
Definition: printer.hh:71
VCSN_RAT_VISIT(ldivide, v)
Definition: printer.hh:127
std::ostream & print(const Aut &aut, std::ostream &out=std::cout, const std::string &fmt="default")
Definition: print.hh:83
const label_t & value() const
Definition: expression.hxx:34
Definition: a-star.hh:8
auto out(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions leaving state s.
Definition: automaton.hh:85
const char * ldivide_
Left-quotient.
Definition: printer.hh:345
static constexpr const char *const superscripts[]
Exponents in UTF-8.
Definition: printer.hh:59
const char * lweight_
External product.
Definition: printer.hh:342
boost::iterator_range< Iterator > initial_sorted_range(Iterator begin, Iterator end, Pred pred, Less less)
The longest initial range of elements matching the predicate.
Definition: algorithm.hh:80
VCSN_RAT_VISIT(compose, v)
Definition: printer.hh:123
VCSN_RAT_VISIT(shuffle, v)
Definition: printer.hh:132
labelset_t_of< context_t > labelset_t
Definition: printer.hh:76
typename detail::weight_t_of_impl< base_t< ValueSet >>::type weight_t_of
Definition: traits.hh:66
bool is_letter_(const node_t &v) const
Whether v is an atom whose label is a letter.
Definition: printer.hh:189
VCSN_RAT_VISIT(add, v)
Definition: printer.hh:134
auto letter_range(Iterator i, Iterator end) const -> boost::iterator_range< Iterator >
Return the longest range of expressions that are letters, in strictly increasing order.
Definition: printer.hh:257
label_t_of< context_t > label_t
Definition: printer.hh:77
bool is_word_(const node_t &v) const
Whether v is an atom whose label is not a letter.
Definition: printer.hh:209
std::ostream & operator()(const value_t &v)
Entry point: print v.
Definition: printer.hh:102
auto print_add_(const add_t &v) -> std::enable_if_t< detail::has_generators_mem_fn< LS >
Print a sum, when the labelset has a genset() function.
Definition: printer.hh:275
const char * compose_
Operator for composition: @.
Definition: printer.hh:350
const char * rangle_
Definition: printer.hh:334
typename super_t::template variadic_t< Type > variadic_t
Definition: printer.hh:88
const char * complement_
Definition: printer.hh:348
VCSN_RAT_VISIT(infiltrate, v)
Definition: printer.hh:126
const bool debug_
Whether to be overly verbose.
Definition: printer.hh:324
unsigned int exponent_threshold_
Definition: printer.hh:368
An inner node with multiple children.
Definition: expression.hh:118
return v
Definition: multiply.hh:361
precedence_t
The possible node precedence levels, increasing.
Definition: printer.hh:34
typename node_t::value_t value_t
A shared_ptr to node_t.
Definition: printer.hh:83
void format(format fmt)
Set output format.
Definition: printer.hxx:69
precedence_t precedence_(const node_t &v) const
The precedence of v (to decide when to print parens).
Definition: printer.hxx:163
ATTRIBUTE_PURE bool shows_left_weight_(const node_t &n)
Whether the left weight shows.
Definition: printer.hh:249
printer< ExpSet > make_printer(const ExpSet &rs, std::ostream &out)
Definition: printer.hh:373
format for_weights() const
A copy of this format, but to print weights.
Definition: format.hh:50
const char * shuffle_
Definition: printer.hh:354
typename super_t::leaf_t leaf_t
Definition: printer.hh:89
const char * zero_
The constants.
Definition: printer.hh:366
VCSN_RAT_VISIT(conjunction, v)
Definition: printer.hh:125
typename super_t::tuple_t tuple_t
Definition: printer.hh:138
const char * lexponent_
Left and right braces for exponents.
Definition: printer.hh:339
typename expressionset_t::identities_t identities_t
Definition: printer.hh:75
auto print_add_(const add_t &v) -> std::enable_if_t<!detail::has_generators_mem_fn< LS >
Print a sum, when the labelset does not have a genset() function.
Definition: printer.hh:311
VCSN_RAT_VISIT(star, v)
Definition: printer.hh:133
const char * lgroup_
Left and right boundaries (typically braces for LaTeX).
Definition: printer.hh:330
const char * tuple_right
Right tuple delimiter.
Definition: printer.hh:363
const char * one_
Definition: printer.hh:367
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
Definition: traits.hh:61
const char * infiltrate_
Definition: printer.hh:353
const char * star_
The expression operators.
Definition: printer.hh:347
printer(const expressionset_t &rs, std::ostream &out)
A printer.
Definition: printer.hxx:40
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:326
const char * lparen_
Left and right parentheses.
Definition: printer.hh:336
const char * add_
Definition: printer.hh:356
void print_child(const node_t &child, precedence_t parent)
Print a child node, given its parent's precedence.
Definition: printer.hxx:281