Vcsn  2.8
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  name,
57  };
58 
60  constexpr static const char* const superscripts[] =
61  {
62  "⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹"
63  };
64 
66  template <typename ExpSet>
67  class printer
68  : public ExpSet::const_visitor
69  {
70  public:
71  using expressionset_t = ExpSet;
72  using super_t = typename expressionset_t::const_visitor;
73  using self_t = printer;
74 
76  using identities_t = typename expressionset_t::identities_t;
80 
82  using node_t = typename super_t::node_t;
84  using value_t = typename node_t::value_t;
85  using inner_t = typename super_t::inner_t;
86  template <type_t Type>
87  using unary_t = typename super_t::template unary_t<Type>;
88  template <type_t Type>
89  using variadic_t = typename super_t::template variadic_t<Type>;
90  using leaf_t = typename super_t::leaf_t;
91 
93  constexpr static const char* me() { return "print"; }
94 
96  printer(const expressionset_t& rs, std::ostream& out);
97 
99  void format(format fmt);
100 
102  std::ostream&
104  {
105  return print_(*v);
106  }
107 
111  void print_child(const node_t& child, precedence_t parent);
112 
113  private:
115  std::ostream& print_(const node_t& v);
116 
118  void print_(const weight_t& w)
119  {
120  rs_.weightset()->print(w, out_, fmt_.for_weights());
121  }
122 
123  VCSN_RAT_VISIT(atom, v);
124  VCSN_RAT_VISIT(compose, v) { print_(v, compose_); }
125  VCSN_RAT_VISIT(complement, v) { print_(v, complement_); }
128  VCSN_RAT_VISIT(ldivide, v) { print_(v, ldivide_); }
130  VCSN_RAT_VISIT(name, v);
131  VCSN_RAT_VISIT(one, v);
132  VCSN_RAT_VISIT(mul, v);
135  VCSN_RAT_VISIT(star, v) { print_(v, star_); }
136  VCSN_RAT_VISIT(add, v) { print_add_(v); }
137  VCSN_RAT_VISIT(transposition, v) { print_(v, transposition_); }
138  VCSN_RAT_VISIT(zero, v);
139 
140  using tuple_t = typename super_t::tuple_t;
141 
142  template <typename Dummy = void>
143  struct visit_tuple
144  {
146  template <size_t I>
147  void print_(const tuple_t& v)
148  {
149  if (I)
150  self_.out_ << self_.tuple_middle;
151  auto rs = detail::project<I>(self_.rs_);
152  auto print = make_printer(rs, self_.out_);
153  print.format(self_.fmt_);
154  print.print_child(*std::get<I>(v.sub()), precedence_t::tuple);
155  }
156 
158  template <size_t... I>
160  {
161  using swallow = int[];
162  (void) swallow
163  {
164  (print_<I>(v),
165  0)...
166  };
167  }
168 
170  void operator()(const tuple_t& v)
171  {
172  self_.out_ << self_.tuple_left;
173  print_(v, labelset_t::indices);
174  self_.out_ << self_.tuple_right;
175  }
176  const self_t& self_;
177  };
178 
179  void visit(const tuple_t& v, std::true_type) override
180  {
181  detail::static_if<context_t::is_lat>
182  ([this](auto&& v){ visit_tuple<decltype(v)>{*this}(v); })
183  (v);
184  }
185 
186 
191  bool is_letter_(const node_t& v) const
192  {
193  auto atom = dynamic_cast<const atom_t*>(&v);
194  return atom && rs_.labelset()->is_letter(atom->value());
195  }
196 
211  bool is_word_(const node_t& v) const
212  {
213  auto atom = dynamic_cast<const atom_t*>(&v);
214  return (atom
215  && (context_t::is_lat
216  || ! rs_.labelset()->is_letter(atom->value())));
217  }
218 
223  bool is_braced_(const node_t& v) const
224  {
225  if (auto s = dynamic_cast<const add_t*>(&v))
226  {
227  auto range = letter_range(s->begin(), s->end());
228  return (end(range) == s->end()
229  && 3 < boost::distance(range));
230  }
231  else
232  return false;
233  }
234 
236  precedence_t precedence_(const node_t& v) const;
237 
239  void print_child_(const node_t& child, const node_t& parent);
240 
242  template <rat::exp::type_t Type>
243  void print_(const unary_t<Type>& n, const char* op);
244 
246  template <rat::exp::type_t Type>
247  void print_(const variadic_t<Type>& n, const char* op);
248 
250  ATTRIBUTE_PURE
251  bool shows_left_weight_(const node_t& n)
252  {
253  return n.type() == rat::type_t::lweight;
254  }
255 
258  template <typename Iterator>
259  auto letter_range(Iterator i, Iterator end) const
260  -> boost::iterator_range<Iterator>
261  {
263  (i, end,
264  [this](const value_t& c) { return is_letter_(*c); },
265  [this](const value_t& lhs, const value_t& rhs)
266  {
267  auto l = std::dynamic_pointer_cast<const atom_t>(lhs)->value();
268  auto r = std::dynamic_pointer_cast<const atom_t>(rhs)->value();
269  const auto& ls = *rs_.labelset();
270  // Require strictly increasing order.
271  return ls.compare(l, r) <= 0;
272  });
273  }
274 
276  template <typename LS = labelset_t>
277  auto print_add_(const add_t& v)
278  -> std::enable_if_t<detail::has_generators_mem_fn<LS>{}, void>
279  {
280  bool first = true;
281  // Use classes for sums of letters.
282  for (auto i = std::begin(v), end = std::end(v);
283  i != end;
284  /* nothing. */)
285  {
286  if (! first)
287  out_ << add_;
288  first = false;
289  // If in front of a row of letters, in strictly increasing
290  // order, issue a class.
291  auto r = letter_range(i, end);
292  if (3 < distance(r))
293  {
294  // Gather the letters.
295  auto letters = std::vector<label_t>{};
296  for (/* nothing. */; i != r.end(); ++i)
297  letters
298  .emplace_back(down_pointer_cast<const atom_t>(*i)->value());
299  vcsn::detail::print_label_class(*rs_.labelset(), letters,
300  out_, fmt_);
301  }
302  else
303  {
304  // Otherwise, just print the child.
305  print_child_(**i, v);
306  ++i;
307  }
308  }
309  }
310 
312  template <typename LS = labelset_t>
313  auto print_add_(const add_t& v)
314  -> std::enable_if_t<!detail::has_generators_mem_fn<LS>{}, void>
315  {
316  print_(v, add_);
317  }
318 
320  std::ostream& out_;
322  class format fmt_;
326  const bool parens_ = !!getenv("VCSN_PARENS");
328  const bool tagged_ = !!getenv("VCSN_PRINT");
329 
334  const char* lgroup_ = nullptr;
335  const char* rgroup_ = nullptr;
337  const char* langle_ = nullptr;
338  const char* rangle_ = nullptr;
340  const char* lparen_ = nullptr;
341  const char* rparen_ = nullptr;
343  const char* lexponent_ = nullptr;
344  const char* rexponent_ = nullptr;
346  const char* lweight_ = nullptr;
347  const char* rweight_ = nullptr;
349  const char* ldivide_ = nullptr;
351  const char* star_ = nullptr;
352  const char* complement_ = nullptr;
354  const char* compose_ = nullptr;
355  const char* transposition_ = nullptr;
356  const char* conjunction_ = nullptr;
357  const char* infiltrate_ = nullptr;
358  const char* shuffle_ = nullptr;
359  const char* product_ = nullptr;
360  const char* add_ = nullptr;
361 
363  const char* tuple_left = nullptr;
365  const char* tuple_middle = nullptr;
367  const char* tuple_right = nullptr;
368 
370  const char* zero_ = nullptr;
371  const char* one_ = nullptr;
374  unsigned int exponent_threshold_ = 0;
375  };
376 
377  template <typename ExpSet>
379  make_printer(const ExpSet& rs, std::ostream& out)
380  {
381  return {rs, out};
382  }
383  } // namespace rat
384 } // namespace vcsn
385 
386 #include <vcsn/core/rat/printer.hxx>
bool is_braced_(const node_t &v) const
Whether is naturally braced.
Definition: printer.hh:223
bool is_word_(const node_t &v) const
Whether v is an atom whose label is not a letter.
Definition: printer.hh:211
std::ostream & print(const Aut &aut, std::ostream &out=std::cout, const std::string &fmt="default")
Definition: print.hh:83
static constexpr const char *const superscripts[]
Exponents in UTF-8.
Definition: printer.hh:60
ExpSet expressionset_t
Definition: printer.hh:71
An inner node with multiple children.
Definition: expression.hh:119
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:84
VCSN_RAT_VISIT(star, v)
Definition: printer.hh:135
const expressionset_t & rs_
The expressionset.
Definition: printer.hh:324
void print_(const tuple_t &v, detail::index_sequence< I... >)
Print all the tapes.
Definition: printer.hh:159
VCSN_RAT_VISIT(compose, v)
Definition: printer.hh:124
void visit(const tuple_t &v, std::true_type) override
Specific handling to using exponents as syntactic sugar.
Definition: printer.hh:179
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:313
precedence_t
The possible node precedence levels, increasing.
Definition: printer.hh:34
automaton conjunction_(const std::vector< automaton > &as, bool lazy, vcsn::detail::index_sequence< I... >)
Bridge helper.
Definition: conjunction.hh:651
An inner node to name the subexpression.
Definition: expression.hh:290
typename detail::context_t_of_impl< base_t< ValueSet > >::type context_t_of
Definition: traits.hh:61
An input/output format for valuesets.
Definition: format.hh:13
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
VCSN_RAT_VISIT(transposition, v)
Definition: printer.hh:137
printer< ExpSet > make_printer(const ExpSet &rs, std::ostream &out)
Definition: printer.hh:379
VCSN_RAT_VISIT(complement, v)
Definition: printer.hh:125
VCSN_RAT_VISIT(infiltrate, v)
Definition: printer.hh:127
typename expressionset_t::const_visitor super_t
Definition: printer.hh:72
typename detail::labelset_t_of_impl< base_t< ValueSet > >::type labelset_t_of
Definition: traits.hh:63
typename super_t::template unary_t< Type > unary_t
Definition: printer.hh:87
void print_(const weight_t &w)
Print a weight.
Definition: printer.hh:118
Definition: a-star.hh:8
weight_t_of< context_t > weight_t
Definition: printer.hh:79
VCSN_RAT_VISIT(add, v)
Definition: printer.hh:136
typename detail::label_t_of_impl< base_t< ValueSet > >::type label_t_of
Definition: traits.hh:62
typename super_t::template variadic_t< Type > variadic_t
Definition: printer.hh:89
typename expressionset_t::identities_t identities_t
Definition: printer.hh:76
typename super_t::tuple_t tuple_t
Definition: printer.hh:140
labelset_t_of< context_t > labelset_t
Definition: printer.hh:77
bool is_letter_(const node_t &v) const
Whether v is an atom whose label is a letter.
Definition: printer.hh:191
static constexpr const char * me()
Name of this algorithm, for error messages.
Definition: printer.hh:93
std::ostream & operator()(const value_t &v)
Entry point: print v.
Definition: printer.hh:103
An inner node implementing a weight.
Definition: expression.hh:256
A static list of size_t.
Definition: tuple.hh:32
typename super_t::inner_t inner_t
Definition: printer.hh:85
Pretty-printer for rational expressions.
Definition: fwd.hh:32
const label_t & value() const
Definition: expression.hxx:34
automaton infiltrate_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I... >)
Variadic bridge helper.
Definition: conjunction.hh:854
return v
Definition: multiply.hh:362
label_t_of< context_t > label_t
Definition: printer.hh:78
context_t_of< expressionset_t > context_t
Definition: printer.hh:75
ATTRIBUTE_PURE bool shows_left_weight_(const node_t &n)
Whether the left weight shows.
Definition: printer.hh:251
#define VCSN_RAT_VISIT(Type, Val)
Definition: visitor.hh:71
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:325
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:277
std::string format(const Value &v, const std::string &format="default")
Definition: algos.hxx:31
VCSN_RAT_VISIT(shuffle, v)
Definition: printer.hh:134
VCSN_RAT_VISIT(conjunction, v)
Definition: printer.hh:126
automaton shuffle_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I... >)
Variadic bridge helper.
Definition: conjunction.hh:801
typename detail::weight_t_of_impl< base_t< ValueSet > >::type weight_t_of
Definition: traits.hh:66
std::ostream & out_
Output stream.
Definition: printer.hh:320
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:259
void print_(std::ostream &o, const T &arg, long)
Serialize arg into o.
Definition: raise.hh:26
VCSN_RAT_VISIT(ldivide, v)
Definition: printer.hh:128
void operator()(const tuple_t &v)
Entry point.
Definition: printer.hh:170
void print_(const tuple_t &v)
Print one tape.
Definition: printer.hh:147
typename super_t::leaf_t leaf_t
Definition: printer.hh:90
typename node_t::value_t value_t
A shared_ptr to node_t.
Definition: printer.hh:84
auto out(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions leaving state s.
Definition: automaton.hh:86
typename super_t::node_t node_t
Actual node, without indirection.
Definition: printer.hh:82