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