Vcsn  2.3a
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(one);
27  CASE(mul);
28  CASE(rweight);
29  CASE(shuffle);
30  CASE(star);
32  CASE(tuple);
33  CASE(zero);
34 #undef CASE
35  }
36  return o;
37  }
38 
39  template <typename ExpSet>
41  std::ostream& out)
42  : out_{out}
43  , rs_{rs}
44  {}
45 
46 
47 #define DEFINE \
48  template <typename ExpSet> \
49  auto \
50  printer<ExpSet>
51 
53  -> std::ostream&
54  {
55  static bool print = !! getenv("VCSN_PRINT");
56  if (print)
57  out_ << '<' << v.type() << "@0x" << address(v) << '>' << vcsn::incendl;
58  if (debug_ && fmt_ == format::latex)
59  out_ << (rs_.identities().is_distributive()
60  ? "{\\color{red}{" : "{\\color{blue}{");
61  v.accept(*this);
62  if (debug_ && fmt_ == format::latex)
63  out_ << "}}";
64  if (print)
65  out_ << vcsn::decendl << "</" << v.type() << '>';
66  return out_;
67  }
68 
69  DEFINE::format(class format fmt)
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. ";
101  exponent_threshold_= 2;
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 = "";
130  exponent_threshold_= 4;
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 = "";
157  exponent_threshold_= 2;
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(one);
183  CASE(mul);
184  CASE(rweight);
185  CASE(shuffle);
186  CASE(star);
188  CASE(tuple);
189  CASE(zero);
190 #undef CASE
191  }
192  abort(); // Unreachable.
193  }
194 
195 #define VISIT(Type) \
196  DEFINE::visit(const Type ## _t& v) \
197  -> void
198 
199  VISIT(lweight)
200  {
201  out_ << langle_;
202  print_(v.weight());
203  out_ << rangle_ << lweight_;
204  print_child_(*v.sub(), v);
205  }
206 
207  VISIT(rweight)
208  {
209  print_child_(*v.sub(), v);
210  out_ << rweight_ << langle_;
211  print_(v.weight());
212  out_ << rangle_;
213  }
214 
215  VISIT(zero)
216  {
217  (void) v;
218  out_ << zero_;
219  }
220 
221  VISIT(one)
222  {
223  (void) v;
224  out_ << one_;
225  }
226 
227  VISIT(atom)
228  {
229  rs_.labelset()->print(v.value(), out_,
230  fmt_.for_labels().meta("!&%|@',[-]<> (){}\n*+:.?"));
231  }
232 
234  VISIT(mul)
235  {
236  for (auto it = begin(v); it != end(v); /* nothing */)
237  {
238  if (it != begin(v))
239  out_ << product_;
240 
241  const auto& i = *it;
242  // Find the size of the sequence of nodes equal to i.
243  auto next =
244  std::find_if(it, end(v),
245  [&](const auto& e) { return !rs_.equal(e, i); });
246  auto count = std::distance(it, next);
247  if (1 < count
248  && (!expressionset_t::context_t::is_lal
249  || ! is_letter_(*i)
250  || exponent_threshold_ < count))
251  {
252  // We can display an exponent.
253  print_child(*i, precedence_t::exponent);
254  if (fmt_ == format::utf8)
255  {
256  // Recursive lambda to display UTF-8 characters
257  // in the correct order.
258  std::function<void(int)> print = [this, &print](int n)
259  {
260  if (n)
261  {
262  print(n / 10);
263  out_ << superscripts[n % 10];
264  }
265  };
266  print(count);
267  }
268  else
269  out_ << lexponent_ << count << rexponent_;
270  it = next;
271  }
272  else
273  {
274  // Print a single node.
275  print_child_(*i, v);
276  ++it;
277  }
278  }
279  }
280 
281  DEFINE::print_child(const node_t& child, precedence_t parent)
282  -> void
283  {
284  static bool force = !! getenv("VCSN_PARENS");
285  bool parent_has_precedence = precedence_(child) <= parent;
286  bool needs_parens =
287  (force
288  || (parent_has_precedence
289  && ! (parent == precedence_t::unary && child.is_unary())
290  && ! is_braced_(child)));
291  if (needs_parens)
292  out_ << lparen_;
293  else if (parent == precedence_t::unary)
294  out_ << lgroup_;
295  print_(child);
296  if (needs_parens)
297  out_ << rparen_;
298  else if (parent == precedence_t::unary)
299  out_ << rgroup_;
300  }
301 
302  DEFINE::print_child_(const node_t& child, const node_t& parent)
303  -> void
304  {
305  print_child(child, precedence_(parent));
306  }
307 
308  template <typename ExpSet>
309  template <type_t Type>
310  auto
311  printer<ExpSet>::print_(const unary_t<Type>& v, const char* op)
312  -> void
313  {
314  print_child_(*v.sub(), v);
315  out_ << op;
316  }
317 
318  template <typename ExpSet>
319  template <type_t Type>
320  auto
321  printer<ExpSet>::print_(const variadic_t<Type>& n, const char* op)
322  -> void
323  {
324  bool first = true;
325  for (const auto& i: n)
326  {
327  if (! first)
328  out_ << op;
329  print_child_(*i, n);
330  first = false;
331  }
332  }
333 
334 #undef VISIT
335 #undef DEFINE
336 
337  } // namespace rat
338 } // namespace vcsn
std::ostream & print_(const node_t &v)
Print v.
Definition: printer.hxx:52
automaton infiltrate_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I... >)
Variadic bridge helper.
Definition: conjunction.hh:888
Implementation of nodes of tuple of rational expressions.
Definition: expression.hh:182
precedence_t
The possible node precedence levels, increasing.
Definition: printer.hh:34
unsigned address(const void *t)
Name pointers, to make them easier to read.
Definition: memory.hh:21
typename super_t::node_t node_t
Actual node, without indirection.
Definition: printer.hh:81
auto out(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions leaving state s.
Definition: automaton.hh:84
static constexpr const char *const superscripts[]
Exponents in UTF-8.
Definition: printer.hh:59
Print for LaTeX.
Definition: format.hh:22
return v
Definition: multiply.hh:361
Definition: a-star.hh:8
std::ostream & decendl(std::ostream &o)
Decrement the indentation, print an end of line, and set the indentation.
Definition: indent.cc:59
void print_(std::ostream &o, const T &arg, long)
Serialize arg into o.
Definition: raise.hh:26
An input/output format for valuesets.
Definition: format.hh:13
variadic< type_t::mul, Context > mul
Definition: fwd.hh:151
weight_node< type_t::lweight, Context > lweight
Definition: fwd.hh:179
ExpSet expressionset_t
Definition: printer.hh:70
typename super_t::template unary_t< Type > unary_t
Definition: printer.hh:86
constant< type_t::one, Context > one
Definition: fwd.hh:113
weight_node< type_t::rweight, Context > rweight
Definition: fwd.hh:182
An inner node implementing a weight.
Definition: expression.hh:264
Indentation relative functions.
Print as rich UTF-8 text, escaped.
Definition: format.hh:30
automaton conjunction_(const std::vector< automaton > &as, bool lazy, vcsn::detail::index_sequence< I... >)
Bridge helper.
Definition: conjunction.hh:652
automaton shuffle_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I... >)
Variadic bridge helper.
Definition: conjunction.hh:802
#define VISIT(Type)
Definition: printer.hxx:195
std::ostream & operator<<(std::ostream &o, type_t t)
Print a expression type.
Definition: printer.hxx:13
Print as plain (ASCII) text, escaped.
Definition: format.hh:28
typename super_t::template variadic_t< Type > variadic_t
Definition: printer.hh:88
constant< type_t::zero, Context > zero
Definition: fwd.hh:110
An inner node with multiple children.
Definition: expression.hh:118
std::ostream & print(const Aut &aut, std::ostream &out=std::cout, const std::string &fmt="default")
Definition: print.hh:83
auto rs
Definition: lift.hh:152
#define CASE(T)
type_t
The possible types of expressions.
Definition: fwd.hh:39
printer(const expressionset_t &rs, std::ostream &out)
A printer.
Definition: printer.hxx:40
std::ostream & incendl(std::ostream &o)
Increment the indentation, print an end of line, and set the indentation.
Definition: indent.cc:54