4 #ifndef LEXY_VISUALIZE_HPP_INCLUDED
5 #define LEXY_VISUALIZE_HPP_INCLUDED
72 lhs.
flags = lhs.flags | rhs;
81 template <
typename Encoding>
86 using encoding = Encoding;
93 template <
typename OutIt>
94 constexpr OutIt
write_str(OutIt out,
const char* str)
100 template <
typename OutIt>
104 *out++ =
static_cast<char>(*str++);
108 template <
int N = 16,
typename OutIt,
typename... Args>
109 constexpr OutIt
write_format(OutIt out,
const char* fmt,
const Args&... args)
111 char buffer[std::size_t(N + 1)];
112 auto count = std::snprintf(
buffer, N, fmt, args...);
115 for (
auto i = 0; i !=
count; ++i)
137 template <
color CodeHead,
color... CodeTail,
typename OutIt>
145 auto write_code = [](OutIt out,
int code) {
148 *out++ =
static_cast<char>((code / 10) +
'0');
149 *out++ =
static_cast<char>((code % 10) +
'0');
153 *out++ =
static_cast<char>(code +
'0');
157 out = write_code(out,
int(CodeHead));
158 ((*out++ =
';', write_code(out,
int(CodeTail))), ...);
164 template <
typename OutIt>
173 template <
typename OutIt,
typename Fn>
176 out = _detail::write_color<_detail::color::cyan, _detail::color::faint>(out, opts);
186 out = _detail::write_color<_detail::color::reset>(out, opts);
193 template <
typename OutputIt>
208 auto c =
static_cast<int>(cp.
value());
231 out = _detail::write_color<_detail::color::faint>(out, opts);
233 out = _detail::write_color<_detail::color::reset>(out, opts);
249 if (opts.tab_width > 0)
253 for (
auto i = 0u; i < opts.tab_width; ++i)
258 out = _detail::write_color<_detail::color::faint>(out, opts);
260 out = _detail::write_color<_detail::color::reset>(out, opts);
287 else if (cp.
value() ==
' ')
293 out = _detail::write_color<_detail::color::faint>(out, opts);
295 out = _detail::write_color<_detail::color::reset>(out, opts);
317 else if (cp.
value() ==
'\\')
330 *out++ =
static_cast<char>(cp.
value());
336 auto c =
static_cast<int>(cp.
value());
348 template <
typename OutputIt,
typename Reader>
356 [[maybe_unused]]
auto write_escaped_byte = [opts](OutputIt out,
unsigned char byte) {
365 using encoding =
typename Reader::encoding;
366 if constexpr (lexy::is_unicode_encoding<encoding>)
370 auto reader = input.reader();
384 reader.reset(result.end);
390 auto begin = reader.position();
392 auto end = reader.position();
395 for (
auto cur =
begin; cur !=
end; ++cur)
397 if constexpr (std::is_same_v<encoding,
399 || std::is_same_v<encoding, lexy::utf8_char_encoding>)
401 out = write_escaped_byte(out,
static_cast<unsigned char>(*cur & 0xFF));
403 else if constexpr (std::is_same_v<encoding, lexy::utf16_encoding>)
405 auto first =
static_cast<unsigned char>((*cur >> 8) & 0xFF);
406 auto second =
static_cast<unsigned char>(*cur & 0xFF);
409 out = write_escaped_byte(out, first);
410 out = write_escaped_byte(out, second);
412 else if constexpr (std::is_same_v<encoding, lexy::utf32_encoding>)
414 auto first =
static_cast<unsigned char>((*cur >> 24) & 0xFF);
415 auto second =
static_cast<unsigned char>((*cur >> 16) & 0xFF);
416 auto third =
static_cast<unsigned char>((*cur >> 8) & 0xFF);
417 auto fourth =
static_cast<unsigned char>(*cur & 0xFF);
420 out = write_escaped_byte(out, first);
421 if (first != 0 || second != 0)
422 out = write_escaped_byte(out, second);
423 if (first != 0 || second != 0 || third != 0)
424 out = write_escaped_byte(out, third);
425 out = write_escaped_byte(out, fourth);
431 if (
count == opts.max_lexeme_width)
439 else if constexpr (lexy::is_text_encoding<encoding>)
449 out = write_escaped_byte(out,
static_cast<unsigned char>(c));
452 if (
count == opts.max_lexeme_width)
460 else if constexpr (lexy::is_byte_encoding<encoding>)
463 for (
auto iter =
lexeme.begin(); iter !=
lexeme.end(); ++iter)
471 if (
count == opts.max_lexeme_width)
479 else if constexpr (lexy::is_node_encoding<encoding>)
488 static_assert(lexy::_detail::error<encoding>,
"unknown encoding");
493 template <
typename OutputIt,
typename Tree,
typename = decltype(
LEXY_DECLVAL(Tree&).traverse())>
504 : label_t{u8
" ", u8
" ", u8
"- ", u8
"- "};
513 = [opts, label, &is_last_child](OutputIt out, std::size_t cur_depth,
bool cur_is_last) {
518 out = _detail::write_color<_detail::color::faint>(out, opts);
521 for (
auto i = 1u; i < cur_depth; ++i)
522 if (is_last_child[i])
535 out = _detail::write_color<_detail::color::reset>(out, opts);
540 std::size_t cur_depth = 0;
541 for (
auto [event, node] : tree.traverse())
543 auto last_child = node.is_last_child();
545 using event_t =
typename decltype(tree.traverse())::event;
549 if (cur_depth <= opts.max_tree_depth)
551 out = write_prefix(out, cur_depth, last_child);
553 out = _detail::write_color<_detail::color::bold>(out, opts);
555 out = _detail::write_color<_detail::color::reset>(out, opts);
557 if (cur_depth == opts.max_tree_depth)
568 is_last_child[cur_depth] = last_child;
579 if (cur_depth <= opts.max_tree_depth)
581 out = write_prefix(out, cur_depth, last_child);
583 out = _detail::write_color<_detail::color::bold>(out, opts);
585 out = _detail::write_color<_detail::color::reset>(out, opts);
587 if (!node.lexeme().empty())
623 std::fputc(c,
_file);
641 std::fputc(c, stderr);
658 std::fputc(c, stdout);
664 template <
typename T>
674 template <
typename T>
681 iterator& operator*() noexcept
685 iterator& operator++(
int) noexcept
690 iterator& operator=(
char c)
695 auto value =
static_cast<unsigned char>(c);
696 if ((value & 0b1100
'0000) != 0b1000'0000)
707 #endif // LEXY_VISUALIZE_HPP_INCLUDED