Vcsn  2.5.dev
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  auto next =
245  std::find_if(it, end(v),
246  [&](const auto& e) { return !rs_.equal(e, i); });
247  auto count = std::distance(it, next);
248  if (1 < count
249  && (!expressionset_t::context_t::is_lal
250  || ! is_letter_(*i)
251  || exponent_threshold_ < count))
252  {
253  // We can display an exponent.
255  if (fmt_ == format::utf8)
256  {
257  // Recursive lambda to display UTF-8 characters
258  // in the correct order.
259  std::function<void(int)> print = [this, &print](int n)
260  {
261  if (n)
262  {
263  print(n / 10);
264  out_ << superscripts[n % 10];
265  }
266  };
267  print(count);
268  }
269  else
270  out_ << lexponent_ << count << rexponent_;
271  it = next;
272  }
273  else
274  {
275  // Print a single node.
276  print_child_(*i, v);
277  ++it;
278  }
279  }
280  }
281 
282  VISIT(name)
283  {
284  if (fmt_ == format::latex)
285  out_ << "\\mathsf{" << v.name_get() << "}";
286  else
287  out_ << v.name_get();
288  }
289 
290  DEFINE::print_child(const node_t& child, precedence_t parent)
291  -> void
292  {
293  bool parent_has_precedence = precedence_(child) <= parent;
294  bool needs_parens =
295  (parens_
296  || (parent_has_precedence
297  && ! (parent == precedence_t::unary && child.is_unary())
298  && ! is_braced_(child)));
299  if (needs_parens)
300  out_ << lparen_;
301  else if (parent == precedence_t::unary)
302  out_ << lgroup_;
303  print_(child);
304  if (needs_parens)
305  out_ << rparen_;
306  else if (parent == precedence_t::unary)
307  out_ << rgroup_;
308  }
309 
310  DEFINE::print_child_(const node_t& child, const node_t& parent)
311  -> void
312  {
313  print_child(child, precedence_(parent));
314  }
315 
316  template <typename ExpSet>
317  template <type_t Type>
318  auto
319  printer<ExpSet>::print_(const unary_t<Type>& v, const char* op)
320  -> void
321  {
322  print_child_(*v.sub(), v);
323  out_ << op;
324  }
325 
326  template <typename ExpSet>
327  template <type_t Type>
328  auto
329  printer<ExpSet>::print_(const variadic_t<Type>& n, const char* op)
330  -> void
331  {
332  bool first = true;
333  for (const auto& i: n)
334  {
335  if (! first)
336  out_ << op;
337  print_child_(*i, n);
338  first = false;
339  }
340  }
341 
342 #undef VISIT
343 #undef DEFINE
344 
345  } // namespace rat
346 } // namespace vcsn
const char * add_
Definition: printer.hh:360
const char * rweight_
Definition: printer.hh:347
static constexpr const char *const superscripts[]
Exponents in UTF-8.
Definition: printer.hh:60
const bool tagged_
Whether to use XML-like tags to highlight the structure.
Definition: printer.hh:328
bool is_letter_(const node_t &v) const
Whether v is an atom whose label is a letter.
Definition: printer.hh:191
const char * transposition_
Definition: printer.hh:355
const char * shuffle_
Definition: printer.hh:358
Implementation of nodes of tuple of rational expressions.
Definition: expression.hh:174
const char * lexponent_
Left and right braces for exponents.
Definition: printer.hh:343
#define CASE(T)
type_t
The possible types of expressions.
Definition: fwd.hh:43
An inner node implementing a weight.
Definition: expression.hh:256
const char * rparen_
Definition: printer.hh:341
return v
Definition: multiply.hh:362
std::string format(const Value &v, const std::string &format="default")
Definition: algos.hxx:31
std::ostream & incendl(std::ostream &o)
Increment the indentation, print an end of line, and set the indentation.
Definition: indent.cc:54
class format fmt_
Output format.
Definition: printer.hh:322
const bool parens_
Whether to be overly verbose.
Definition: printer.hh:326
std::ostream & out_
Output stream.
Definition: printer.hh:320
const char * infiltrate_
Definition: printer.hh:357
format for_labels() const
A copy of this format, but to print labels.
Definition: format.hh:42
const char * complement_
Definition: printer.hh:352
const char * rexponent_
Definition: printer.hh:344
void print_child(const node_t &child, precedence_t parent)
Print a child node, given its parent&#39;s precedence.
Definition: printer.hxx:290
const char * compose_
Operator for composition: @.
Definition: printer.hh:354
An inner node with multiple children.
Definition: expression.hh:119
const char * langle_
Left and right angle brackets for weights.
Definition: printer.hh:337
const char * tuple_left
Left tuple delimiter.
Definition: printer.hh:363
bool is_braced_(const node_t &v) const
Whether is naturally braced.
Definition: printer.hh:223
auto out(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions leaving state s.
Definition: automaton.hh:86
Print for LaTeX.
Definition: format.hh:22
Print as rich UTF-8 text, escaped.
Definition: format.hh:30
const char * tuple_middle
Tuple tape separator.
Definition: printer.hh:365
typename super_t::node_t node_t
Actual node, without indirection.
Definition: printer.hh:82
const char * one_
Definition: printer.hh:371
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
Definition: a-star.hh:8
bool is_word_(const node_t &v) const
Whether v is an atom whose label is not a letter.
Definition: printer.hh:211
printer(const expressionset_t &rs, std::ostream &out)
A printer.
Definition: printer.hxx:41
precedence_t
The possible node precedence levels, increasing.
Definition: printer.hh:34
typename super_t::template variadic_t< Type > variadic_t
Definition: printer.hh:89
An inner node to name the subexpression.
Definition: expression.hh:290
unsigned int exponent_threshold_
Definition: printer.hh:372
An input/output format for valuesets.
Definition: format.hh:13
Naming an expression.
void print_child_(const node_t &child, const node_t &parent)
Print a child node, given its parent.
Definition: printer.hxx:310
#define VISIT(Type)
Definition: printer.hxx:196
std::ostream & print(const Aut &aut, std::ostream &out=std::cout, const std::string &fmt="default")
Definition: print.hh:83
const char * lparen_
Left and right parentheses.
Definition: printer.hh:340
const char * rangle_
Definition: printer.hh:338
const char * star_
The expression operators.
Definition: printer.hh:351
std::ostream & print_(const node_t &v)
Print v.
Definition: printer.hxx:53
Print as plain (ASCII) text, escaped.
Definition: format.hh:28
const expressionset_t & rs_
The expressionset.
Definition: printer.hh:324
const char * zero_
The constants.
Definition: printer.hh:370
Indentation relative functions.
unsigned address(const void *t)
Name pointers, to make them easier to read.
Definition: memory.hh:21
typename super_t::template unary_t< Type > unary_t
Definition: printer.hh:87
std::ostream & decendl(std::ostream &o)
Decrement the indentation, print an end of line, and set the indentation.
Definition: indent.cc:59
std::ostream & operator<<(std::ostream &o, type_t t)
Print a expression type.
Definition: printer.hxx:13
const char * product_
Definition: printer.hh:359
void print_(std::ostream &o, const T &arg, long)
Serialize arg into o.
Definition: raise.hh:26
ExpSet expressionset_t
Definition: printer.hh:71
const char * lweight_
External product.
Definition: printer.hh:346
const char * tuple_right
Right tuple delimiter.
Definition: printer.hh:367
const char * meta() const
Characters that need to be escaped.
Definition: format.hh:72
const char * rgroup_
Definition: printer.hh:335
const char * lgroup_
Left and right boundaries (typically braces for LaTeX).
Definition: printer.hh:334
const char * conjunction_
Definition: printer.hh:356