visualize.hpp
Go to the documentation of this file.
1 // Copyright (C) 2020-2023 Jonathan Müller and lexy contributors
2 // SPDX-License-Identifier: BSL-1.0
3 
4 #ifndef LEXY_VISUALIZE_HPP_INCLUDED
5 #define LEXY_VISUALIZE_HPP_INCLUDED
6 
7 #include <cstdio>
11 #include <lexy/lexeme.hpp>
12 
13 //=== visualization_options ===//
14 namespace lexy
15 {
17 {
19 
26 
29 
31  visualize_space = 1 << 3,
32 };
33 
35 {
36  return visualization_flags(int(lhs) | int(rhs));
37 }
38 
41 {
42  static constexpr unsigned char max_tree_depth_limit = 32;
43 
46 
52  unsigned char max_lexeme_width = 0;
55  unsigned char tab_width = 0;
56 
57  constexpr bool is_set(visualization_flags f) const noexcept
58  {
59  return (flags & f) != 0;
60  }
61 
63  {
64  auto copy = *this;
65  copy.flags = visualization_flags(copy.flags & ~f);
66  return copy;
67  }
68 
70  visualization_flags rhs) noexcept
71  {
72  lhs.flags = lhs.flags | rhs;
73  return lhs;
74  }
75 };
76 } // namespace lexy
77 
78 //=== visualize_to ===//
79 namespace lexy::_detail
80 {
81 template <typename Encoding>
82 constexpr auto make_literal_lexeme(const typename Encoding::char_type* str, std::size_t length)
83 {
84  struct reader
85  {
86  using encoding = Encoding;
87  using iterator = const typename Encoding::char_type*;
88  };
89 
90  return lexy::lexeme<reader>(str, str + length);
91 }
92 
93 template <typename OutIt>
94 constexpr OutIt write_str(OutIt out, const char* str)
95 {
96  while (*str)
97  *out++ = *str++;
98  return out;
99 }
100 template <typename OutIt>
101 constexpr OutIt write_str(OutIt out, const LEXY_CHAR8_T* str)
102 {
103  while (*str)
104  *out++ = static_cast<char>(*str++);
105  return out;
106 }
107 
108 template <int N = 16, typename OutIt, typename... Args>
109 constexpr OutIt write_format(OutIt out, const char* fmt, const Args&... args)
110 {
111  char buffer[std::size_t(N + 1)];
112  auto count = std::snprintf(buffer, N, fmt, args...);
113  LEXY_ASSERT(count <= N, "buffer not big enough");
114 
115  for (auto i = 0; i != count; ++i)
116  *out++ = buffer[i];
117  return out;
118 }
119 
120 enum class color
121 {
122  reset = 0,
123  bold = 1,
124  faint = 2,
125  italic = 3,
126 
127  black = 30,
128  red = 31,
129  green = 32,
130  yellow = 33,
131  blue = 34,
132  magenta = 35,
133  cyan = 36,
134  white = 37,
135 };
136 
137 template <color CodeHead, color... CodeTail, typename OutIt>
138 constexpr OutIt write_color(OutIt out, visualization_options opts)
139 {
140  if (!opts.is_set(visualize_use_color))
141  return out;
142 
143  out = write_str(out, "\033[");
144 
145  auto write_code = [](OutIt out, int code) {
146  if (code > 10)
147  {
148  *out++ = static_cast<char>((code / 10) + '0');
149  *out++ = static_cast<char>((code % 10) + '0');
150  }
151  else
152  {
153  *out++ = static_cast<char>(code + '0');
154  }
155  return out;
156  };
157  out = write_code(out, int(CodeHead));
158  ((*out++ = ';', write_code(out, int(CodeTail))), ...);
159 
160  *out++ = 'm';
161  return out;
162 }
163 
164 template <typename OutIt>
165 constexpr OutIt write_ellipsis(OutIt out, visualization_options opts)
166 {
167  if (opts.is_set(visualize_use_unicode))
168  return _detail::write_str(out, u8"…");
169  else
170  return _detail::write_str(out, "...");
171 }
172 
173 template <typename OutIt, typename Fn>
174 constexpr OutIt write_special_char(OutIt out, visualization_options opts, Fn inner)
175 {
176  out = _detail::write_color<_detail::color::cyan, _detail::color::faint>(out, opts);
177  if (opts.is_set(visualize_use_unicode))
178  out = _detail::write_str(out, u8"⟨");
179  else
180  out = _detail::write_str(out, "\\");
181 
182  out = inner(out);
183 
184  if (opts.is_set(visualize_use_unicode))
185  out = _detail::write_str(out, u8"⟩");
186  out = _detail::write_color<_detail::color::reset>(out, opts);
187  return out;
188 }
189 } // namespace lexy::_detail
190 
191 namespace lexy
192 {
193 template <typename OutputIt>
194 OutputIt visualize_to(OutputIt out, lexy::code_point cp, visualization_options opts = {})
195 {
196  if (!cp.is_valid())
197  {
198  out = _detail::write_special_char(out, opts, [opts](OutputIt out) {
199  if (opts.is_set(visualize_use_unicode))
200  return _detail::write_str(out, "U+????");
201  else
202  return _detail::write_str(out, "u????");
203  });
204  return out;
205  }
206  else if (cp.is_control())
207  {
208  auto c = static_cast<int>(cp.value());
209  switch (c)
210  {
211  case '\0':
212  out = _detail::write_special_char(out, opts, [opts](OutputIt out) {
213  if (opts.is_set(visualize_use_unicode))
214  return _detail::write_str(out, "NUL");
215  else
216  return _detail::write_str(out, "0");
217  });
218  break;
219  case '\r':
220  out = _detail::write_special_char(out, opts, [opts](OutputIt out) {
221  if (opts.is_set(visualize_use_unicode))
222  return _detail::write_str(out, "CR");
223  else
224  return _detail::write_str(out, "r");
225  });
226  break;
227 
228  case '\n':
229  if (opts.is_set(visualize_use_symbols))
230  {
231  out = _detail::write_color<_detail::color::faint>(out, opts);
232  out = _detail::write_str(out, u8"⏎");
233  out = _detail::write_color<_detail::color::reset>(out, opts);
234  }
235  else if (opts.is_set(visualize_use_unicode))
236  {
237  out = _detail::write_special_char(out, opts, [](OutputIt out) {
238  return _detail::write_str(out, "LF");
239  });
240  }
241  else
242  {
243  out = _detail::write_special_char(out, opts, [](OutputIt out) {
244  return _detail::write_str(out, "n");
245  });
246  }
247  break;
248  case '\t':
249  if (opts.tab_width > 0)
250  {
251  // We print that many space characters.
252  // This is recursion, but the recursive call does not recurse further.
253  for (auto i = 0u; i < opts.tab_width; ++i)
254  out = visualize_to(out, lexy::code_point(' '), opts);
255  }
256  else if (opts.is_set(visualize_use_symbols))
257  {
258  out = _detail::write_color<_detail::color::faint>(out, opts);
259  out = _detail::write_str(out, u8"⇨");
260  out = _detail::write_color<_detail::color::reset>(out, opts);
261  }
262  else if (opts.is_set(visualize_use_unicode))
263  {
264  out = _detail::write_special_char(out, opts, [](OutputIt out) {
265  return _detail::write_str(out, "HT");
266  });
267  }
268  else
269  {
270  out = _detail::write_special_char(out, opts, [](OutputIt out) {
271  return _detail::write_str(out, "t");
272  });
273  }
274  break;
275 
276  default:
277  out = _detail::write_special_char(out, opts, [opts, c](OutputIt out) {
278  if (opts.is_set(visualize_use_unicode))
279  return _detail::write_format(out, "U+%04X", c);
280  else
281  return _detail::write_format(out, "u%04X", c);
282  });
283  break;
284  }
285  return out;
286  }
287  else if (cp.value() == ' ')
288  {
289  if (opts.is_set(visualize_space))
290  {
291  if (opts.is_set(visualize_use_symbols))
292  {
293  out = _detail::write_color<_detail::color::faint>(out, opts);
294  out = _detail::write_str(out, u8"␣");
295  out = _detail::write_color<_detail::color::reset>(out, opts);
296  }
297  else if (opts.is_set(visualize_use_unicode))
298  {
299  out = _detail::write_special_char(out, opts, [](OutputIt out) {
300  return _detail::write_str(out, "SP");
301  });
302  }
303  else
304  {
305  out = _detail::write_special_char(out, opts, [](OutputIt out) {
306  return _detail::write_str(out, "u0020");
307  });
308  }
309  }
310  else
311  {
312  *out++ = ' ';
313  }
314 
315  return out;
316  }
317  else if (cp.value() == '\\')
318  {
319  if (!opts.is_set(visualize_use_unicode))
320  out = _detail::write_special_char(out, opts, [](OutputIt out) {
321  return _detail::write_str(out, "\\");
322  });
323  else
324  *out++ = '\\'; // Doesn't need escaping if we can use unicode.
325  return out;
326  }
327  else if (cp.is_ascii())
328  {
329  // ASCII, non-control character, print as-is.
330  *out++ = static_cast<char>(cp.value());
331  return out;
332  }
333  else
334  {
335  out = _detail::write_special_char(out, opts, [opts, cp](OutputIt out) {
336  auto c = static_cast<int>(cp.value());
337  if (opts.is_set(visualize_use_unicode))
338  return _detail::write_format(out, "U+%04X", c);
339  else if (cp.is_bmp())
340  return _detail::write_format(out, "u%04X", c);
341  else
342  return _detail::write_format(out, "U%08X", c);
343  });
344  return out;
345  }
346 }
347 
348 template <typename OutputIt, typename Reader>
349 OutputIt visualize_to(OutputIt out, lexy::lexeme<Reader> lexeme,
350  [[maybe_unused]] visualization_options opts = {})
351 {
352  // We need to ensure that we're not printing more "code points" than `opts.max_lexeme_width`,
353  // or unlimited if `opts.max_lexeme_width == 0`.
354  // The trick is to count and check for `count == opts.max_lexeme_width` after increment.
355 
356  [[maybe_unused]] auto write_escaped_byte = [opts](OutputIt out, unsigned char byte) {
357  return _detail::write_special_char(out, opts, [opts, byte](OutputIt out) {
358  if (opts.is_set(visualize_use_unicode))
359  return _detail::write_format(out, "0x%02X", byte);
360  else
361  return _detail::write_format(out, "x%02X", byte);
362  });
363  };
364 
365  using encoding = typename Reader::encoding;
366  if constexpr (std::is_same_v<encoding, lexy::ascii_encoding> //
367  || std::is_same_v<encoding, lexy::default_encoding>)
368  {
369  auto count = 0u;
370  for (char c : lexeme)
371  {
372  // If the character is in fact ASCII, visualize the code point.
373  // Otherwise, visualize as byte.
375  out = visualize_to(out, lexy::code_point(static_cast<char32_t>(c)), opts);
376  else
377  out = write_escaped_byte(out, static_cast<unsigned char>(c));
378 
379  ++count;
380  if (count == opts.max_lexeme_width)
381  {
382  out = _detail::write_ellipsis(out, opts);
383  break;
384  }
385  }
386  return out;
387  }
388  else if constexpr (std::is_same_v<encoding, lexy::utf8_encoding> //
389  || std::is_same_v<encoding, lexy::utf8_char_encoding> //
390  || std::is_same_v<encoding, lexy::utf16_encoding> //
391  || std::is_same_v<encoding, lexy::utf32_encoding>)
392  {
393  // Parse the individual code points, and write them out.
395  auto reader = input.reader();
396 
397  auto count = 0u;
398  while (true)
399  {
400  if (auto result = lexy::_detail::parse_code_point(reader);
401  result.error == lexy::_detail::cp_error::eof)
402  {
403  // No more code points in the lexeme, finish.
404  break;
405  }
406  else if (result.error == lexy::_detail::cp_error::success)
407  {
408  // Consume and visualize.
409  reader.set_position(result.end);
410  out = visualize_to(out, lexy::code_point(result.cp), opts);
411  }
412  else
413  {
414  // Recover from the failed code point.
415  auto begin = reader.position();
416  lexy::_detail::recover_code_point(reader, result);
417  auto end = reader.position();
418 
419  // Visualize each skipped code unit as byte.
420  for (auto cur = begin; cur != end; ++cur)
421  {
422  if constexpr (std::is_same_v<encoding,
424  || std::is_same_v<encoding, lexy::utf8_char_encoding>)
425  {
426  out = write_escaped_byte(out, static_cast<unsigned char>(*cur & 0xFF));
427  }
428  else if constexpr (std::is_same_v<encoding, lexy::utf16_encoding>)
429  {
430  auto first = static_cast<unsigned char>((*cur >> 8) & 0xFF);
431  auto second = static_cast<unsigned char>(*cur & 0xFF);
432 
433  if (first != 0)
434  out = write_escaped_byte(out, first);
435  out = write_escaped_byte(out, second);
436  }
437  else if constexpr (std::is_same_v<encoding, lexy::utf32_encoding>)
438  {
439  auto first = static_cast<unsigned char>((*cur >> 24) & 0xFF);
440  auto second = static_cast<unsigned char>((*cur >> 16) & 0xFF);
441  auto third = static_cast<unsigned char>((*cur >> 8) & 0xFF);
442  auto fourth = static_cast<unsigned char>(*cur & 0xFF);
443 
444  if (first != 0)
445  out = write_escaped_byte(out, first);
446  if (first != 0 || second != 0)
447  out = write_escaped_byte(out, second);
448  if (first != 0 || second != 0 || third != 0)
449  out = write_escaped_byte(out, third);
450  out = write_escaped_byte(out, fourth);
451  }
452  }
453  }
454 
455  ++count;
456  if (count == opts.max_lexeme_width)
457  {
458  out = _detail::write_ellipsis(out, opts);
459  break;
460  }
461  }
462  return out;
463  }
464  else if constexpr (std::is_same_v<encoding, lexy::byte_encoding>)
465  {
466  auto count = 0u;
467  for (auto iter = lexeme.begin(); iter != lexeme.end(); ++iter)
468  {
469  // Write each byte.
470  out = _detail::write_special_char(out, opts, [c = *iter](OutputIt out) {
471  return _detail::write_format(out, "%02X", c);
472  });
473 
474  ++count;
475  if (count == opts.max_lexeme_width)
476  {
477  out = _detail::write_ellipsis(out, opts);
478  break;
479  }
480  }
481  return out;
482  }
483  else
484  {
485  static_assert(lexy::_detail::error<encoding>, "unknown encoding");
486  return out;
487  }
488 }
489 
490 template <typename OutputIt, typename Tree, typename = decltype(LEXY_DECLVAL(Tree&).traverse())>
491 OutputIt visualize_to(OutputIt out, const Tree& tree, visualization_options opts = {})
492 {
493  struct label_t
494  {
495  const LEXY_CHAR_OF_u8* space;
496  const LEXY_CHAR_OF_u8* line;
497  const LEXY_CHAR_OF_u8* end;
498  const LEXY_CHAR_OF_u8* branch;
499  };
500  auto label = opts.is_set(visualize_use_unicode) ? label_t{u8" ", u8"│ ", u8"└──", u8"├──"}
501  : label_t{u8" ", u8" ", u8"- ", u8"- "};
502 
503  // True if the node currently opened at the depth is the last child of its parent,
504  // false otherwise.
505  bool is_last_child[visualization_options::max_tree_depth_limit] = {};
507 
508  // Writes the prefix using the last child information.
509  auto write_prefix
510  = [opts, label, &is_last_child](OutputIt out, std::size_t cur_depth, bool cur_is_last) {
511  if (cur_depth == 0)
512  // Root node doesn't have a prefix.
513  return out;
514 
515  out = _detail::write_color<_detail::color::faint>(out, opts);
516 
517  // We begin at depth 1, as depth 0 doesn't require a prefix.
518  for (auto i = 1u; i < cur_depth; ++i)
519  if (is_last_child[i])
520  // If the current node at that depth is the last child, we just indent.
521  out = _detail::write_str(out, label.space);
522  else
523  // Otherwise, we need to carry the line.
524  out = _detail::write_str(out, label.line);
525 
526  // Print the final branching symbol for the current node.
527  if (cur_is_last)
528  out = _detail::write_str(out, label.end);
529  else
530  out = _detail::write_str(out, label.branch);
531 
532  out = _detail::write_color<_detail::color::reset>(out, opts);
533  return out;
534  };
535 
536  // Traverse and print the tree.
537  std::size_t cur_depth = 0;
538  for (auto [event, node] : tree.traverse())
539  {
540  auto last_child = node.is_last_child();
541 
542  using event_t = typename decltype(tree.traverse())::event;
543  switch (event)
544  {
545  case event_t::enter:
546  if (cur_depth <= opts.max_tree_depth)
547  {
548  out = write_prefix(out, cur_depth, last_child);
549 
550  out = _detail::write_color<_detail::color::bold>(out, opts);
551  out = _detail::write_str(out, node.kind().name());
552  out = _detail::write_color<_detail::color::reset>(out, opts);
553 
554  if (cur_depth == opts.max_tree_depth)
555  {
556  // Print an ellipsis instead of children.
557  out = _detail::write_str(out, ": ");
558  out = _detail::write_ellipsis(out, opts);
559  out = _detail::write_str(out, "\n");
560  }
561  else
562  {
563  // Print a newline and prepare for children.
564  out = _detail::write_str(out, ":\n");
565  is_last_child[cur_depth] = last_child;
566  }
567  }
568  ++cur_depth;
569  break;
570 
571  case event_t::exit:
572  --cur_depth;
573  break;
574 
575  case event_t::leaf:
576  if (cur_depth <= opts.max_tree_depth)
577  {
578  out = write_prefix(out, cur_depth, last_child);
579 
580  out = _detail::write_color<_detail::color::bold>(out, opts);
581  out = _detail::write_str(out, node.kind().name());
582  out = _detail::write_color<_detail::color::reset>(out, opts);
583 
584  if (!node.lexeme().empty())
585  {
586  out = _detail::write_str(out, ": ");
587  out = visualize_to(out, node.lexeme(), opts | lexy::visualize_space);
588  }
589 
590  out = _detail::write_str(out, "\n");
591  }
592  break;
593  }
594  }
595 
596  return out;
597 }
598 } // namespace lexy
599 
600 //=== visualize ===//
601 namespace lexy
602 {
604 {
605  std::FILE* _file;
606 
607  explicit constexpr cfile_output_iterator(std::FILE* file) : _file(file) {}
608 
609  auto operator*() const noexcept
610  {
611  return *this;
612  }
613  auto operator++(int) const noexcept
614  {
615  return *this;
616  }
617 
619  {
620  std::fputc(c, _file);
621  return *this;
622  }
623 };
624 
626 template <typename T>
627 void visualize(std::FILE* file, const T& obj, visualization_options opts = {})
628 {
629  visualize_to(cfile_output_iterator{file}, obj, opts);
630 }
631 } // namespace lexy
632 
633 //=== visualization_display_width ===//
634 namespace lexy
635 {
636 template <typename T>
637 std::size_t visualization_display_width(const T& obj, visualization_options opts = {})
638 {
639  struct iterator
640  {
641  std::size_t width;
642 
643  iterator& operator*() noexcept
644  {
645  return *this;
646  }
647  iterator& operator++(int) noexcept
648  {
649  return *this;
650  }
651 
652  iterator& operator=(char c)
653  {
654  // We're having ASCII or UTF-8 characters.
655  // All unicode characters used occupy a single cell,
656  // so we just need to count all code units that are not continuation bytes.
657  auto value = static_cast<unsigned char>(c);
658  if ((value & 0b1100'0000) != 0b1000'0000)
659  ++width;
660  return *this;
661  }
662  };
663 
664  // Disable usage of color, as they introduce additional characters that must nobe counted.
665  return visualize_to(iterator{0}, obj, opts.reset(visualize_use_color)).width;
666 }
667 } // namespace lexy
668 
669 #endif // LEXY_VISUALIZE_HPP_INCLUDED
670 
lexy::_detail::color
color
Definition: visualize.hpp:120
lexy::_detail::color::white
@ white
lexy::_detail::write_ellipsis
constexpr OutIt write_ellipsis(OutIt out, visualization_options opts)
Definition: visualize.hpp:165
lexy::cfile_output_iterator::_file
std::FILE * _file
Definition: visualize.hpp:605
lexy::_detail::color::green
@ green
lexy::cfile_output_iterator::cfile_output_iterator
constexpr cfile_output_iterator(std::FILE *file)
Definition: visualize.hpp:607
lexy::_detail::color::magenta
@ magenta
lexy::visualize_use_color
@ visualize_use_color
Visualization can use ANSI color escape sequences.
Definition: visualize.hpp:23
lexy::_detail::write_format
constexpr OutIt write_format(OutIt out, const char *fmt, const Args &... args)
Definition: visualize.hpp:109
lexy::_detail::color::yellow
@ yellow
magic_enum::char_type
string_view::value_type char_type
Definition: magic_enum.hpp:145
lexy::visualization_display_width
std::size_t visualization_display_width(const T &obj, visualization_options opts={})
Definition: visualize.hpp:637
lexy::_detail::write_str
constexpr OutIt write_str(OutIt out, const char *str)
Definition: visualize.hpp:94
config.hpp
lexy::visualization_options::max_tree_depth
unsigned char max_tree_depth
Definition: visualize.hpp:49
lexy::_detail::parse_code_point
constexpr cp_result< Reader > parse_code_point(Reader reader)
Definition: _detail/code_point.hpp:142
lexy::_detail::write_color
constexpr OutIt write_color(OutIt out, visualization_options opts)
Definition: visualize.hpp:138
lexy::code_point::is_control
constexpr bool is_control() const noexcept
Definition: code_point.hpp:49
lexy::visualization_options
Options that control visualization.
Definition: visualize.hpp:40
lexy::_detail::color::bold
@ bold
lexy::visualization_options::is_set
constexpr bool is_set(visualization_flags f) const noexcept
Definition: visualize.hpp:57
lexy::_detail::recover_code_point
constexpr void recover_code_point(Reader &reader, cp_result< Reader > result)
Definition: _detail/code_point.hpp:338
lexy::visualization_options::tab_width
unsigned char tab_width
Definition: visualize.hpp:55
lexy::visualization_options::operator|
constexpr friend visualization_options operator|(visualization_options lhs, visualization_flags rhs) noexcept
Definition: visualize.hpp:69
lexy::visualization_options::reset
constexpr visualization_options reset(visualization_flags f) const noexcept
Definition: visualize.hpp:62
lexy::code_point::is_ascii
constexpr bool is_ascii() const noexcept
Definition: code_point.hpp:36
LEXY_CHAR_OF_u8
#define LEXY_CHAR_OF_u8
Definition: config.hpp:115
lexy::range_input
Definition: range_input.hpp:14
lexy::cfile_output_iterator
Definition: visualize.hpp:603
magic_enum::detail::value
constexpr E value(std::size_t i) noexcept
Definition: magic_enum.hpp:664
lexy::_detail::cp_error::eof
@ eof
lexy
Definition: any_ref.hpp:12
LEXY_PRECONDITION
#define LEXY_PRECONDITION(Expr)
Definition: assert.hpp:36
cx::end
constexpr auto end(const C &c) -> decltype(c.end())
Definition: wildcards.hpp:686
lexy::code_point::value
constexpr auto value() const noexcept
Definition: code_point.hpp:30
lexy::operator|
constexpr auto operator|(First first, Second second)
Composes two callbacks.
Definition: composition.hpp:100
lexy::_detail::make_literal_lexeme
constexpr auto make_literal_lexeme(const typename Encoding::char_type *str, std::size_t length)
Definition: visualize.hpp:82
lexy::visualize
void visualize(std::FILE *file, const T &obj, visualization_options opts={})
Writes the visualization to the FILE.
Definition: visualize.hpp:627
lexy::visualization_options::max_tree_depth_limit
static constexpr unsigned char max_tree_depth_limit
Definition: visualize.hpp:42
lexy::visualize_to
OutputIt visualize_to(OutputIt out, lexy::code_point cp, visualization_options opts={})
Definition: visualize.hpp:194
range_input.hpp
lexy::count
constexpr auto count
Sink that counts all arguments.
Definition: fold.hpp:88
lexeme.hpp
lexy::visualize_use_symbols
@ visualize_use_symbols
Visualization can use Unicode symbols e.g. for newline/space instead of the code point.
Definition: visualize.hpp:25
lexy::code_point::is_bmp
constexpr bool is_bmp() const noexcept
Definition: code_point.hpp:40
lexy::visualization_options::max_lexeme_width
unsigned char max_lexeme_width
Definition: visualize.hpp:52
lexy::utf8_encoding
An encoding where the input is assumed to be valid UTF-8.
Definition: encoding.hpp:84
lexy::_detail::color::reset
@ reset
lexy::_detail::is_ascii
constexpr bool is_ascii(CharT c)
Definition: encoding.hpp:269
code_point.hpp
lexy::visualize_fancy
@ visualize_fancy
Visualization can use unicode, color and symbols.
Definition: visualize.hpp:28
lexy::cfile_output_iterator::operator=
cfile_output_iterator & operator=(char c)
Definition: visualize.hpp:618
f
static FILE * f
Definition: minitrace.cpp:74
cx::begin
constexpr auto begin(const C &c) -> decltype(c.begin())
Definition: wildcards.hpp:661
lexy::code_point::is_valid
constexpr bool is_valid() const noexcept
Definition: code_point.hpp:44
wildcards::detail::is_set_state::first
@ first
lexy::cfile_output_iterator::operator*
auto operator*() const noexcept
Definition: visualize.hpp:609
lexy::_detail
Definition: any_ref.hpp:12
lexy::buffer
Definition: buffer.hpp:81
lexy::visualization_flags
visualization_flags
Definition: visualize.hpp:16
lexy::visualize_default
@ visualize_default
Definition: visualize.hpp:18
lexy::lexeme
Definition: lexeme.hpp:16
lexy::_detail::cp_error::success
@ success
lexyd::byte
constexpr auto byte
Matches an arbitrary byte.
Definition: byte.hpp:51
lexy::_detail::color::red
@ red
lexy::lexeme
lexeme(const Reader &, typename Reader::iterator) -> lexeme< typename Reader::canonical_reader >
lexyd::ascii::space
constexpr auto space
Definition: ascii.hpp:112
lexy::_detail::color::italic
@ italic
lexy::visualize_space
@ visualize_space
Visualize space ' ' as visible character/symbol.
Definition: visualize.hpp:31
lexy::_detail::color::blue
@ blue
LEXY_DECLVAL
#define LEXY_DECLVAL(...)
Definition: config.hpp:24
lexy::visualize_use_unicode
@ visualize_use_unicode
Visualization can use unicode characters.
Definition: visualize.hpp:21
lexy::_detail::color::cyan
@ cyan
lexy::cfile_output_iterator::operator++
auto operator++(int) const noexcept
Definition: visualize.hpp:613
lexy::_detail::color::black
@ black
lexy::visualization_options::flags
visualization_flags flags
Boolean flags.
Definition: visualize.hpp:45
lexy::_detail::color::faint
@ faint
LEXY_ASSERT
#define LEXY_ASSERT(Expr, Msg)
Definition: assert.hpp:37
LEXY_CHAR8_T
#define LEXY_CHAR8_T
Definition: config.hpp:116
lexy::code_point
A unicode code point.
Definition: code_point.hpp:24
lexy::_detail::write_special_char
constexpr OutIt write_special_char(OutIt out, visualization_options opts, Fn inner)
Definition: visualize.hpp:174


behaviortree_cpp_v4
Author(s): Davide Faconti
autogenerated on Fri Jun 28 2024 02:20:08