Vcsn  2.2
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 
12  inline
13  std::ostream&
14  operator<<(std::ostream& o, type_t t)
15  {
16  switch (t)
17  {
18 #define CASE(T) case type_t::T: o << #T; break
19  CASE(atom);
23  CASE(ldiv);
24  CASE(lweight);
25  CASE(one);
26  CASE(prod);
27  CASE(rweight);
28  CASE(shuffle);
29  CASE(star);
30  CASE(sum);
32  CASE(tuple);
33  CASE(zero);
34 #undef CASE
35  }
36  return o;
37  }
38 
39  template <typename ExpSet>
40  inline
42  std::ostream& out)
43  : out_{out}
44  , rs_{rs}
45  {}
46 
47 
48 #define DEFINE \
49  template <typename ExpSet> \
50  inline \
51  auto \
52  printer<ExpSet>
53 
54  DEFINE::operator()(const node_t& v)
55  -> std::ostream&
56  {
57  static bool print = !! getenv("VCSN_PRINT");
58  if (print)
59  out_ << '<' << v.type() << "@0x" << address(v) << '>' << vcsn::incendl;
60  if (debug_ && fmt_ == format::latex)
61  out_ << (rs_.identities().is_distributive()
62  ? "{\\color{red}{" : "{\\color{blue}{");
63  v.accept(*this);
64  if (debug_ && fmt_ == format::latex)
65  out_ << "}}";
66  if (print)
67  out_ << vcsn::decendl << "</" << v.type() << '>';
68  return out_;
69  }
70 
71  DEFINE::format(class format fmt)
72  -> void
73  {
74  fmt_ = fmt;
75  if (fmt_ == format::latex)
76  {
77  lgroup_ = "{";
78  rgroup_ = "}";
79  langle_ = " \\left\\langle ";
80  rangle_ = " \\right\\rangle ";
81  lparen_ = "\\left(";
82  rparen_ = "\\right)";
83  lexponent_ = "^{";
84  rexponent_ = "}";
85  star_ = "^{*}";
86  complement_ = "^{c}";
87  transposition_ = "^{T}";
88  conjunction_ = " \\& ";
89  infiltration_ = " \\uparrow ";
90  shuffle_ = " \\between ";
91  product_ = " \\, ";
92  sum_ = (rs_.identities().is_distributive() ? " \\oplus "
93  : " + ");
94  zero_ = "\\emptyset";
95  one_ = "\\varepsilon";
96  lmul_ = "\\,";
97  rmul_ = "\\,";
98  ldiv_ = " \\backslash ";
99  tuple_left = " \\left. ";
100  tuple_middle = " \\middle| ";
101  tuple_right = " \\right. ";
102  exponent_threshold_= 2;
103  }
104  else if (fmt_ == format::text)
105  {
106  lgroup_ = "";
107  rgroup_ = "";
108  langle_ = "<";
109  rangle_ = ">";
110  lparen_ = "(";
111  rparen_ = ")";
112  lexponent_ = "{";
113  rexponent_ = "}";
114  star_ = "*";
115  complement_ = "{c}";
116  transposition_ = "{T}";
117  conjunction_ = "&";
118  infiltration_ = "&:";
119  shuffle_ = ":";
120  product_ = "";
121  sum_ = "+";
122  zero_ = "\\z";
123  one_ = "\\e";
124  lmul_ = "";
125  rmul_ = "";
126  ldiv_ = "{\\}";
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  complement_ = "ᶜ";
142  transposition_ = "ᵗ";
143  conjunction_ = "&";
144  infiltration_ = "&:";
145  shuffle_ = ":";
146  product_ = "";
147  sum_ = "+";
148  zero_ = "∅";
149  one_ = "ε";
150  lmul_ = "";
151  rmul_ = "";
152  ldiv_ = "{\\}";
153  tuple_left = "";
154  tuple_middle = "|";
155  tuple_right = "";
156  exponent_threshold_= 2;
157  }
158  else
159  raise("expression: invalid format: ", fmt_);
160  }
161 
162  DEFINE::precedence_(const node_t& v) const
163  -> precedence_t
164  {
165  if (is_word_(v))
166  return precedence_t::word;
167  else
168  switch (v.type())
169  {
170 #define CASE(Type) \
171  case exp::type_t::Type: \
172  return precedence_t::Type
173  CASE(atom);
174  CASE(complement);
175  CASE(conjunction);
177  CASE(ldiv);
178  CASE(lweight);
179  CASE(one);
180  CASE(prod);
181  CASE(rweight);
182  CASE(shuffle);
183  CASE(star);
184  CASE(sum);
186  CASE(tuple);
187  CASE(zero);
188 #undef CASE
189  }
190  abort(); // Unreachable.
191  }
192 
193 #define VISIT(Type) \
194  DEFINE::visit(const Type ## _t& v) \
195  -> void
196 
197  VISIT(lweight)
198  {
199  out_ << langle_;
200  rs_.weightset()->print(v.weight(), out_, fmt_.for_weights());
201  out_ << rangle_ << lmul_;
202  print_child_(*v.sub(), v);
203  }
204 
205  VISIT(rweight)
206  {
207  print_child_(*v.sub(), v);
208  out_ << rmul_ << langle_;
209  rs_.weightset()->print(v.weight(), out_, fmt_.for_weights());
210  out_ << rangle_;
211  }
212 
213  VISIT(zero)
214  {
215  (void) v;
216  out_ << zero_;
217  }
218 
219  VISIT(one)
220  {
221  (void) v;
222  out_ << one_;
223  }
224 
225  VISIT(atom)
226  {
227  rs_.labelset()->print(v.value(), out_, fmt_.for_labels());
228  }
229 
230  VISIT(prod)
231  {
232  for (auto it = begin(v); it != end(v); /* nothing */)
233  {
234  if (it != begin(v))
235  out_ << product_;
236 
237  const auto& i = *it;
238  // Find the size of the sequence of nodes equal to i.
239  auto next =
240  std::find_if(it, end(v),
241  [&](const auto& e) { return !rs_.equal(e, i); });
242  auto count = std::distance(it, next);
243  if (1 < count
244  && (!expressionset_t::context_t::is_lal
245  || ! is_letter_(*i)
246  || exponent_threshold_ < count))
247  {
248  // We can display an exponent.
249  print_child(*i, precedence_t::exponent);
250  if (fmt_ == format::utf8)
251  {
252  // Recursive lambda to display UTF-8 characters
253  // in the correct order.
254  std::function<void(int)> print = [this, &print](int n)
255  {
256  if (n)
257  {
258  print(n / 10);
259  out_ << superscripts[n % 10];
260  }
261  };
262  print(count);
263  }
264  else
265  out_ << lexponent_ << count << rexponent_;
266  it = next;
267  }
268  else
269  {
270  // Print a single node.
271  print_child_(*i, v);
272  ++it;
273  }
274  }
275  }
276 
277  DEFINE::print_child(const node_t& child, precedence_t parent)
278  -> void
279  {
280  static bool force = !! getenv("VCSN_PARENS");
281  bool parent_has_precedence = precedence_(child) <= parent;
282  bool needs_parens =
283  (force
284  || (parent_has_precedence
285  && ! (parent == precedence_t::unary && child.is_unary())
286  && ! is_braced_(child)));
287  if (needs_parens)
288  out_ << lparen_;
289  else if (parent == precedence_t::unary)
290  out_ << lgroup_;
291  operator()(child);
292  if (needs_parens)
293  out_ << rparen_;
294  else if (parent == precedence_t::unary)
295  out_ << rgroup_;
296  }
297 
298  DEFINE::print_child_(const node_t& child, const node_t& parent)
299  -> void
300  {
301  print_child(child, precedence_(parent));
302  }
303 
304  template <typename ExpSet>
305  template <type_t Type>
306  inline
307  auto
308  printer<ExpSet>::print_(const unary_t<Type>& v, const char* op)
309  -> void
310  {
311  print_child_(*v.sub(), v);
312  out_ << op;
313  }
314 
315  template <typename ExpSet>
316  template <type_t Type>
317  inline
318  auto
319  printer<ExpSet>::print_(const variadic_t<Type>& n, const char* op)
320  -> void
321  {
322  bool first = true;
323  for (const auto& i: n)
324  {
325  if (! first)
326  out_ << op;
327  print_child_(*i, n);
328  first = false;
329  }
330  }
331 
332 #undef VISIT
333 #undef DEFINE
334 
335  } // namespace rat
336 } // namespace vcsn
printer(const expressionset_t &rs, std::ostream &out)
A printer.
Definition: printer.hxx:41
std::ostream & incendl(std::ostream &o)
Increment the indentation, print an end of line, and set the indentation.
Definition: indent.cc:54
Print as rich UTF-8 text, escaped.
Definition: format.hh:28
type_t
The possible types of expressions.
Definition: fwd.hh:39
#define CASE(T)
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
Print for LaTeX.
Definition: format.hh:20
automaton infiltration_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I... >)
Variadic bridge helper.
Definition: conjunction.hh:628
#define VISIT(Type)
Definition: printer.hxx:193
An input/output format for valuesets.
Definition: format.hh:11
Indentation relative functions.
An inner node with multiple children.
Definition: expression.hh:118
ExpSet expressionset_t
Definition: printer.hh:68
typename super_t::template unary_t< Type > unary_t
Definition: printer.hh:82
constant< type_t::one, Context > one
Definition: fwd.hh:111
auto out(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions leaving state s.
Definition: automaton.hh:56
static constexpr const char *const superscripts[]
Exponents in UTF-8.
Definition: printer.hh:58
std::ostream & operator<<(std::ostream &o, type_t t)
Definition: printer.hxx:14
Print as plain (ASCII) text, escaped.
Definition: format.hh:26
typename super_t::template variadic_t< Type > variadic_t
Definition: printer.hh:84
weight_node< type_t::lweight, Context > lweight
Definition: fwd.hh:174
auto rs
Definition: lift.hh:151
constant< type_t::zero, Context > zero
Definition: fwd.hh:108
variadic< type_t::prod, Context > prod
Definition: fwd.hh:137
std::ostream & print(const Aut &aut, std::ostream &out, const std::string &fmt)
Definition: print.hh:77
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:494
An inner node implementing a weight.
Definition: expression.hh:264
weight_node< type_t::rweight, Context > rweight
Definition: fwd.hh:177
automaton shuffle_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I... >)
Variadic bridge helper.
Definition: conjunction.hh:543
void print_(const unary_t< Type > &n, const char *op)
Print a unary node.
Implementation of nodes of tuple of rational expressions.
Definition: expression.hh:182
typename super_t::node_t node_t
Actual node, without indirection.
Definition: printer.hh:77
int address(const void *t)
Name pointers, to make them easier to read.
Definition: memory.hh:22