Vcsn  2.8
Be Rational
printer.hxx
Go to the documentation of this file.
1 #include <vcsn/misc/escape.hh>
2 #include <vcsn/misc/indent.hh>
3 #include <vcsn/misc/memory.hh> // address
4 #include <vcsn/misc/raise.hh>
6 
7 namespace vcsn
8 {
9  namespace rat
10  {
11  inline
12  std::ostream&
13  operator<<(std::ostream& o, type_t t)
14  {
15  switch (t)
16  {
17 #define CASE(T) case type_t::T: o << #T; break
18  CASE(add);
19  CASE(atom);
21  CASE(compose);
24  CASE(ldivide);
25  CASE(lweight);
26  CASE(name);
27  CASE(one);
28  CASE(mul);
29  CASE(rweight);
30  CASE(shuffle);
31  CASE(star);
33  CASE(tuple);
34  CASE(zero);
35 #undef CASE
36  }
37  return o;
38  }
39 
40  template <typename ExpSet>
42  std::ostream& out)
43  : out_{out}
44  , rs_{rs}
45  {}
46 
47 
48 #define DEFINE \
49  template <typename ExpSet> \
50  auto \
51  printer<ExpSet>
52 
54  -> std::ostream&
55  {
56  if (tagged_)
57  out_ << '<' << v.type() << "@0x" << address(v) << '>' << vcsn::incendl;
58  if (parens_ && fmt_ == format::latex)
59  out_ << (rs_.identities().is_distributive()
60  ? "{\\color{red}{" : "{\\color{blue}{");
61  v.accept(*this);
62  if (parens_ && fmt_ == format::latex)
63  out_ << "}}";
64  if (tagged_)
65  out_ << vcsn::decendl << "</" << v.type() << '>';
66  return out_;
67  }
68 
70  -> void
71  {
72  fmt_ = fmt;
73  if (fmt_ == format::latex)
74  {
75  lgroup_ = "{";
76  rgroup_ = "}";
77  langle_ = " \\left\\langle ";
78  rangle_ = " \\right\\rangle ";
79  lparen_ = "\\left(";
80  rparen_ = "\\right)";
81  lexponent_ = "^{";
82  rexponent_ = "}";
83  star_ = "^{*}";
84  compose_ = "@";
85  complement_ = "^{c}";
86  transposition_ = "^{T}";
87  conjunction_ = " \\& ";
88  infiltrate_ = " \\uparrow ";
89  shuffle_ = " \\between ";
90  product_ = " \\, ";
91  add_ = (rs_.identities().is_distributive() ? " \\oplus "
92  : " + ");
93  zero_ = "\\emptyset";
94  one_ = "\\varepsilon";
95  lweight_ = "\\,";
96  rweight_ = "\\,";
97  ldivide_ = " \\backslash ";
98  tuple_left = " \\left. ";
99  tuple_middle = " \\middle| ";
100  tuple_right = " \\right. ";
102  }
103  else if (fmt_ == format::text)
104  {
105  lgroup_ = "";
106  rgroup_ = "";
107  langle_ = "<";
108  rangle_ = ">";
109  lparen_ = "(";
110  rparen_ = ")";
111  lexponent_ = "{";
112  rexponent_ = "}";
113  star_ = "*";
114  complement_ = "{c}";
115  compose_ = "@";
116  transposition_ = "{T}";
117  conjunction_ = "&";
118  infiltrate_ = "&:";
119  shuffle_ = ":";
120  product_ = "";
121  add_ = "+";
122  zero_ = "\\z";
123  one_ = "\\e";
124  lweight_ = "";
125  rweight_ = "";
126  ldivide_ = "{\\}";
127  tuple_left = "";
128  tuple_middle = "|";
129  tuple_right = "";
131  }
132  else if (fmt_ == format::utf8)
133  {
134  lgroup_ = "";
135  rgroup_ = "";
136  langle_ = "⟨";
137  rangle_ = "⟩";
138  lparen_ = "(";
139  rparen_ = ")";
140  star_ = "*";
141  compose_ = "@";
142  complement_ = "ᶜ";
143  transposition_ = "ᵗ";
144  conjunction_ = "&";
145  infiltrate_ = "&:";
146  shuffle_ = ":";
147  product_ = "";
148  add_ = "+";
149  zero_ = "∅";
150  one_ = "ε";
151  lweight_ = "";
152  rweight_ = "";
153  ldivide_ = "{\\}";
154  tuple_left = "";
155  tuple_middle = "|";
156  tuple_right = "";
158  }
159  else
160  raise("expression: invalid format: ", fmt_);
161  }
162 
163  DEFINE::precedence_(const node_t& v) const
164  -> precedence_t
165  {
166  if (is_word_(v))
167  return precedence_t::word;
168  else
169  switch (v.type())
170  {
171 #define CASE(Type) \
172  case exp::type_t::Type: \
173  return precedence_t::Type
174  CASE(add);
175  CASE(atom);
176  CASE(complement);
177  CASE(compose);
178  CASE(conjunction);
179  CASE(infiltrate);
180  CASE(ldivide);
181  CASE(lweight);
182  CASE(name);
183  CASE(one);
184  CASE(mul);
185  CASE(rweight);
186  CASE(shuffle);
187  CASE(star);
189  CASE(tuple);
190  CASE(zero);
191 #undef CASE
192  }
193  abort(); // Unreachable.
194  }
195 
196 #define VISIT(Type) \
197  DEFINE::visit(const Type ## _t& v) \
198  -> void
199 
200  VISIT(lweight)
201  {
202  out_ << langle_;
203  print_(v.weight());
204  out_ << rangle_ << lweight_;
205  print_child_(*v.sub(), v);
206  }
207 
208  VISIT(rweight)
209  {
210  print_child_(*v.sub(), v);
211  out_ << rweight_ << langle_;
212  print_(v.weight());
213  out_ << rangle_;
214  }
215 
216  VISIT(zero)
217  {
218  (void) v;
219  out_ << zero_;
220  }
221 
222  VISIT(one)
223  {
224  (void) v;
225  out_ << one_;
226  }
227 
228  VISIT(atom)
229  {
230  rs_.labelset()->print(v.value(), out_,
231  fmt_.for_labels().meta("!&%|@',[-]<> (){}\n*+:.?"));
232  }
233 
235  VISIT(mul)
236  {
237  for (auto it = begin(v); it != end(v); /* nothing */)
238  {
239  if (it != begin(v))
240  out_ << product_;
241 
242  const auto& i = *it;
243  // Find the size of the sequence of nodes equal to i.
244  const auto next =
245  std::find_if(it, end(v),
246  [&](const auto& e) { return !rs_.equal(e, i); });
247  const auto count = std::distance(it, next);
248  if (1 < count
249  && (!is_letter_(*i) || exponent_threshold_ < count))
250  {
251  // We can display an exponent.
253  if (fmt_ == format::utf8)
254  {
255  // Recursive lambda to display UTF-8 characters
256  // in the correct order.
257  std::function<void(int)> print = [this, &print](int n)
258  {
259  if (n)
260  {
261  print(n / 10);
262  out_ << superscripts[n % 10];
263  }
264  };
265  print(count);
266  }
267  else
268  out_ << lexponent_ << count << rexponent_;
269  it = next;
270  }
271  else
272  {
273  // Print a single node.
274  print_child_(*i, v);
275  ++it;
276  }
277  }
278  }
279 
280  VISIT(name)
281  {
282  if (fmt_ == format::latex)
283  out_ << "\\mathsf{" << v.name_get() << "}";
284  else
285  out_ << v.name_get();
286  }
287 
288  DEFINE::print_child(const node_t& child, precedence_t parent)
289  -> void
290  {
291  bool parent_has_precedence = precedence_(child) <= parent;
292  bool needs_parens =
293  (parens_
294  || (parent_has_precedence
295  && ! (parent == precedence_t::unary && child.is_unary())
296  && ! is_braced_(child)));
297  if (needs_parens)
298  out_ << lparen_;
299  else if (parent == precedence_t::unary)
300  out_ << lgroup_;
301  print_(child);
302  if (needs_parens)
303  out_ << rparen_;
304  else if (parent == precedence_t::unary)
305  out_ << rgroup_;
306  }
307 
308  DEFINE::print_child_(const node_t& child, const node_t& parent)
309  -> void
310  {
311  print_child(child, precedence_(parent));
312  }
313 
314  template <typename ExpSet>
315  template <type_t Type>
316  auto
317  printer<ExpSet>::print_(const unary_t<Type>& v, const char* op)
318  -> void
319  {
320  print_child_(*v.sub(), v);
321  out_ << op;
322  }
323 
324  template <typename ExpSet>
325  template <type_t Type>
326  auto
327  printer<ExpSet>::print_(const variadic_t<Type>& n, const char* op)
328  -> void
329  {
330  bool first = true;
331  for (const auto& i: n)
332  {
333  if (! first)
334  out_ << op;
335  print_child_(*i, n);
336  first = false;
337  }
338  }
339 
340 #undef VISIT
341 #undef DEFINE
342 
343  } // namespace rat
344 } // namespace vcsn
bool is_braced_(const node_t &v) const
Whether is naturally braced.
Definition: printer.hh:223
const char * lparen_
Left and right parentheses.
Definition: printer.hh:340
const char * one_
Definition: printer.hh:371
bool is_word_(const node_t &v) const
Whether v is an atom whose label is not a letter.
Definition: printer.hh:211
format for_labels() const
A copy of this format, but to print labels.
Definition: format.hh:42
const char * infiltrate_
Definition: printer.hh:357
#define CASE(T)
const char * lgroup_
Left and right boundaries (typically braces for LaTeX).
Definition: printer.hh:334
std::ostream & print(const Aut &aut, std::ostream &out=std::cout, const std::string &fmt="default")
Definition: print.hh:83
unsigned address(const void *t)
Name pointers, to make them easier to read.
Definition: memory.hh:21
static constexpr const char *const superscripts[]
Exponents in UTF-8.
Definition: printer.hh:60
const char * rparen_
Definition: printer.hh:341
ExpSet expressionset_t
Definition: printer.hh:71
class format fmt_
Output format.
Definition: printer.hh:322
An inner node with multiple children.
Definition: expression.hh:119
const bool tagged_
Whether to use XML-like tags to highlight the structure.
Definition: printer.hh:328
const char * rangle_
Definition: printer.hh:338
const char * star_
The expression operators.
Definition: printer.hh:351
void print_child_(const node_t &child, const node_t &parent)
Print a child node, given its parent.
Definition: printer.hxx:308
printer(const expressionset_t &rs, std::ostream &out)
A printer.
Definition: printer.hxx:41
const expressionset_t & rs_
The expressionset.
Definition: printer.hh:324
const char * rweight_
Definition: printer.hh:347
const char * zero_
The constants.
Definition: printer.hh:370
const char * complement_
Definition: printer.hh:352
const char * lexponent_
Left and right braces for exponents.
Definition: printer.hh:343
const bool parens_
Whether to be overly verbose.
Definition: printer.hh:326
const char * transposition_
Definition: printer.hh:355
precedence_t
The possible node precedence levels, increasing.
Definition: printer.hh:34
const char * rgroup_
Definition: printer.hh:335
const char * meta() const
Characters that need to be escaped.
Definition: format.hh:72
std::ostream & print_(const node_t &v)
Print v.
Definition: printer.hxx:53
An inner node to name the subexpression.
Definition: expression.hh:290
Print as rich UTF-8 text, escaped.
Definition: format.hh:30
An input/output format for valuesets.
Definition: format.hh:13
const char * tuple_middle
Tuple tape separator.
Definition: printer.hh:365
const char * add_
Definition: printer.hh:360
const char * ldivide_
Left-quotient.
Definition: printer.hh:349
precedence_t precedence_(const node_t &v) const
The precedence of v (to decide when to print parens).
Definition: printer.hxx:163
typename super_t::template unary_t< Type > unary_t
Definition: printer.hh:87
type_t
The possible types of expressions.
Definition: fwd.hh:43
Definition: a-star.hh:8
const char * compose_
Operator for composition: @.
Definition: printer.hh:354
std::ostream & incendl(std::ostream &o)
Increment the indentation, print an end of line, and set the indentation.
Definition: indent.cc:54
const char * lweight_
External product.
Definition: printer.hh:346
std::ostream & decendl(std::ostream &o)
Decrement the indentation, print an end of line, and set the indentation.
Definition: indent.cc:59
Implementation of nodes of tuple of rational expressions.
Definition: expression.hh:174
typename super_t::template variadic_t< Type > variadic_t
Definition: printer.hh:89
unsigned int exponent_threshold_
Number of consecutive identical letters that we decide to write using exponents.
Definition: printer.hh:374
const char * rexponent_
Definition: printer.hh:344
Print as plain (ASCII) text, escaped.
Definition: format.hh:28
Naming an expression.
bool is_letter_(const node_t &v) const
Whether v is an atom whose label is a letter.
Definition: printer.hh:191
An inner node implementing a weight.
Definition: expression.hh:256
const char * shuffle_
Definition: printer.hh:358
const char * langle_
Left and right angle brackets for weights.
Definition: printer.hh:337
return v
Definition: multiply.hh:362
const char * tuple_right
Right tuple delimiter.
Definition: printer.hh:367
Print for LaTeX.
Definition: format.hh:22
const char * conjunction_
Definition: printer.hh:356
const char * product_
Definition: printer.hh:359
std::string format(const Value &v, const std::string &format="default")
Definition: algos.hxx:31
std::ostream & out_
Output stream.
Definition: printer.hh:320
std::ostream & operator<<(std::ostream &o, type_t t)
Print a expression type.
Definition: printer.hxx:13
void print_(std::ostream &o, const T &arg, long)
Serialize arg into o.
Definition: raise.hh:26
Indentation relative functions.
void print_child(const node_t &child, precedence_t parent)
Print a child node, given its parent&#39;s precedence.
Definition: printer.hxx:288
#define VISIT(Type)
Definition: printer.hxx:196
const char * tuple_left
Left tuple delimiter.
Definition: printer.hh:363
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