| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715 |
- #ifndef BOOST_PARSER_DETAIL_PRINTING_HPP
- #define BOOST_PARSER_DETAIL_PRINTING_HPP
- #include <boost/parser/parser_fwd.hpp>
- #include <boost/parser/tuple.hpp>
- #include <boost/parser/detail/detection.hpp>
- #include <boost/parser/detail/hl.hpp>
- #include <boost/parser/detail/text/unpack.hpp>
- #if defined(_MSC_VER) && defined(BOOST_PARSER_TRACE_TO_VS_OUTPUT)
- #include <boost/parser/detail/vs_output_stream.hpp>
- #endif
- #include <boost/parser/detail/text/transcode_view.hpp>
- #include <iomanip>
- #include <iostream>
- #include <optional>
- #include <sstream>
- #include <string>
- #include <variant>
- #include <cctype>
- namespace boost { namespace parser { namespace detail {
- template<typename Context>
- decltype(auto) _indent(Context const & context);
- template<typename Char>
- std::ostream & print_char(std::ostream & os, Char c)
- {
- if constexpr (
- #if defined(__cpp_char8_t)
- std::is_same_v<
- char8_t,
- std::remove_cv_t<std::remove_reference_t<Char>>>
- #else
- false
- #endif
- ) {
- os << char(c);
- } else {
- os << c;
- }
- return os;
- }
- enum { parser_component_limit = 4 };
- template<
- typename Context,
- typename Parser,
- typename DelimiterParser,
- typename MinType,
- typename MaxType>
- void print_parser(
- Context const & context,
- repeat_parser<Parser, DelimiterParser, MinType, MaxType> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context, typename Parser>
- void print_parser(
- Context const & context,
- opt_parser<Parser> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context, typename ParserTuple>
- void print_parser(
- Context const & context,
- or_parser<ParserTuple> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context, typename ParserTuple, typename DelimiterParser>
- void print_parser(
- Context const & context,
- perm_parser<ParserTuple, DelimiterParser> const & parser,
- std::ostream & os,
- int components = 0);
- template<
- typename Context,
- typename ParserTuple,
- typename BacktrackingTuple,
- typename CombiningGroups>
- void print_parser(
- Context const & context,
- seq_parser<ParserTuple, BacktrackingTuple, CombiningGroups> const &
- parser,
- std::ostream & os,
- int components = 0);
- template<typename Context, typename Parser, typename Action>
- void print_parser(
- Context const & context,
- action_parser<Parser, Action> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context, typename Parser, typename F>
- void print_parser(
- Context const & context,
- transform_parser<Parser, F> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context, typename Parser>
- void print_parser(
- Context const & context,
- omit_parser<Parser> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context, typename Parser>
- void print_parser(
- Context const & context,
- raw_parser<Parser> const & parser,
- std::ostream & os,
- int components = 0);
- #if defined(BOOST_PARSER_DOXYGEN) || BOOST_PARSER_USE_CONCEPTS
- template<typename Context, typename Parser>
- void print_parser(
- Context const & context,
- string_view_parser<Parser> const & parser,
- std::ostream & os,
- int components = 0);
- #endif
- template<typename Context, typename Parser>
- void print_parser(
- Context const & context,
- lexeme_parser<Parser> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context, typename Parser>
- void print_parser(
- Context const & context,
- no_case_parser<Parser> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context, typename Parser, typename SkipParser>
- void print_parser(
- Context const & context,
- skip_parser<Parser, SkipParser> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context, typename Parser, bool FailOnMatch>
- void print_parser(
- Context const & context,
- expect_parser<Parser, FailOnMatch> const & parser,
- std::ostream & os,
- int components = 0);
- template<
- typename Context,
- bool UseCallbacks,
- typename Parser,
- typename Attribute,
- typename LocalState,
- typename ParamsTuple>
- void print_parser(
- Context const & context,
- rule_parser<
- UseCallbacks,
- Parser,
- Attribute,
- LocalState,
- ParamsTuple> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context, typename T>
- void print_parser(
- Context const & context,
- symbol_parser<T> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context, typename Predicate>
- void print_parser(
- Context const & context,
- eps_parser<Predicate> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context>
- void print_parser(
- Context const & context,
- eps_parser<nope> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context>
- void print_parser(
- Context const & context,
- eoi_parser const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context, typename Atribute>
- void print_parser(
- Context const & context,
- attr_parser<Atribute> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context, typename Expected, typename AttributeType>
- void print_parser(
- Context const & context,
- char_parser<Expected, AttributeType> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context>
- void print_parser(
- Context const & context,
- digit_parser const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context>
- void print_parser(
- Context const & context,
- char_subrange_parser<hex_digit_subranges> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context>
- void print_parser(
- Context const & context,
- char_subrange_parser<control_subranges> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context>
- void print_parser(
- Context const & context,
- char_set_parser<punct_chars> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context>
- void print_parser(
- Context const & context,
- char_set_parser<symb_chars> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context>
- void print_parser(
- Context const & context,
- char_set_parser<lower_case_chars> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context>
- void print_parser(
- Context const & context,
- char_set_parser<upper_case_chars> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context, typename Expected, typename AttributeType>
- void print_parser(
- Context const & context,
- omit_parser<char_parser<Expected, AttributeType>> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context, typename StrIter, typename StrSentinel>
- void print_parser(
- Context const & context,
- string_parser<StrIter, StrSentinel> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context, typename StrIter, typename StrSentinel>
- void print_parser(
- Context const & context,
- omit_parser<string_parser<StrIter, StrSentinel>> const & parser,
- std::ostream & os,
- int components = 0);
- template<
- typename Context,
- typename Quotes,
- typename Escapes,
- typename CharParser>
- void print_parser(
- Context const & context,
- quoted_string_parser<Quotes, Escapes, CharParser> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context, bool NewlinesOnly, bool NoNewlines>
- void print_parser(
- Context const & context,
- ws_parser<NewlinesOnly, NoNewlines> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context>
- void print_parser(
- Context const & context,
- bool_parser const & parser,
- std::ostream & os,
- int components = 0);
- template<
- typename Context,
- typename T,
- int Radix,
- int MinDigits,
- int MaxDigits,
- typename Expected>
- void print_parser(
- Context const & context,
- uint_parser<T, Radix, MinDigits, MaxDigits, Expected> const & parser,
- std::ostream & os,
- int components = 0);
- template<
- typename Context,
- typename T,
- int Radix,
- int MinDigits,
- int MaxDigits,
- typename Expected>
- void print_parser(
- Context const & context,
- int_parser<T, Radix, MinDigits, MaxDigits, Expected> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context, typename T>
- void print_parser(
- Context const & context,
- float_parser<T> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context>
- void print_parser(
- Context const & context,
- float_parser<float> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context>
- void print_parser(
- Context const & context,
- float_parser<double> const & parser,
- std::ostream & os,
- int components = 0);
- template<typename Context, typename SwitchValue, typename OrParser>
- void print_parser(
- Context const & context,
- switch_parser<SwitchValue, OrParser> const & parser,
- std::ostream & os,
- int components = 0);
- enum { trace_indent_factor = 2 };
- inline void trace_indent(std::ostream & os, int indent)
- {
- for (int i = 0, end = trace_indent_factor * indent; i != end; ++i) {
- os << ' ';
- }
- }
- template<typename Iter, typename Sentinel, int SizeofValueType>
- struct trace_input_impl
- {
- static void call(
- std::ostream & os,
- Iter first_,
- Sentinel last_,
- bool quote,
- int64_t trace_input_cps)
- {
- auto utf8 = BOOST_PARSER_DETAIL_TEXT_SUBRANGE(first_, last_) | text::as_utf8;
- auto first = utf8.begin();
- auto last = utf8.end();
- if (quote)
- os << '"';
- for (int64_t i = 0; i < trace_input_cps && first != last;
- ++i, ++first) {
- detail::print_char(os, *first);
- }
- if (quote)
- os << '"';
- }
- };
- template<typename Iter, typename Sentinel>
- struct trace_input_impl<Iter, Sentinel, 1>
- {
- static void call(
- std::ostream & os,
- Iter first_,
- Sentinel last_,
- bool quote,
- int64_t trace_input_cps)
- {
- auto r = BOOST_PARSER_DETAIL_TEXT_SUBRANGE(first_, last_);
- auto r_unpacked =
- detail::text::unpack_iterator_and_sentinel(first_, last_);
- auto utf32 = r | text::as_utf32;
- auto first = utf32.begin();
- auto const last = utf32.end();
- for (int64_t i = 0; i < trace_input_cps && first != last; ++i) {
- ++first;
- }
- if (quote)
- os << '"';
- auto first_repacked = r_unpacked.repack(first.base());
- for (Iter it = first_, end = first_repacked; it != end; ++it) {
- detail::print_char(os, *it);
- }
- if (quote)
- os << '"';
- }
- };
- template<typename Iter, typename Sentinel>
- inline void trace_input(
- std::ostream & os,
- Iter first,
- Sentinel last,
- bool quote = true,
- int64_t trace_input_cps = 8)
- {
- trace_input_impl<Iter, Sentinel, sizeof(*first)>::call(
- os, first, last, quote, trace_input_cps);
- }
- template<typename Iter, typename Sentinel>
- inline void trace_begin_match(
- std::ostream & os,
- Iter first,
- Sentinel last,
- int indent,
- std::string_view name)
- {
- detail::trace_indent(os, indent);
- os << "[begin " << name << "; input=";
- detail::trace_input(os, first, last);
- os << "]" << std::endl;
- }
- template<typename Iter, typename Sentinel>
- inline void trace_end_match(
- std::ostream & os,
- Iter first,
- Sentinel last,
- int indent,
- std::string_view name)
- {
- detail::trace_indent(os, indent);
- os << "[end " << name << "; input=";
- detail::trace_input(os, first, last);
- os << "]" << std::endl;
- }
- template<typename Iter, typename Sentinel, typename Context>
- void trace_prefix(
- std::ostream & os,
- Iter first,
- Sentinel last,
- Context const & context,
- std::string_view name)
- {
- int & indent = detail::_indent(context);
- detail::trace_begin_match(os, first, last, indent, name);
- ++indent;
- }
- template<typename Iter, typename Sentinel, typename Context>
- void trace_suffix(
- std::ostream & os,
- Iter first,
- Sentinel last,
- Context const & context,
- std::string_view name)
- {
- int & indent = detail::_indent(context);
- --indent;
- detail::trace_end_match(os, first, last, indent, name);
- }
- template<typename T>
- using streamable =
- decltype(std::declval<std::ostream &>() << std::declval<T const &>());
- template<typename T, bool Streamable = is_detected_v<streamable, T>>
- struct printer
- {
- std::ostream & operator()(std::ostream & os, T const &)
- {
- return os << "<<unprintable-value>>";
- }
- };
- template<typename T>
- void print_printable(std::ostream & os, T const & x)
- {
- os << x;
- }
- inline void print_printable(std::ostream & os, char c)
- {
- if (std::isprint(c)) {
- os << "'" << c << "'";
- } else {
- unsigned char c_ = c;
- os << "'\\x" << std::hex << std::setfill('0') << (uint32_t)c_
- << "'";
- }
- }
- inline void print_printable(std::ostream & os, char32_t c)
- {
- if (c < 256) {
- os << "U";
- detail::print_printable(os, (char)c);
- } else {
- os << "U'\\U" << std::hex << std::setfill('0') << (int32_t)c << "'";
- }
- }
- template<typename T>
- struct printer<T, true>
- {
- std::ostream & operator()(std::ostream & os, T const & x)
- {
- detail::print_printable(os, x);
- return os;
- }
- };
- template<typename T>
- constexpr bool is_variant_v = enable_variant<T>;
- template<typename Attribute>
- inline void print(std::ostream & os, Attribute const & attr)
- {
- using just_attribute =
- std::remove_cv_t<std::remove_reference_t<Attribute>>;
- if constexpr (is_tuple<just_attribute>{}) {
- os << "(";
- bool first = true;
- hl::for_each(attr, [&](auto const & a) {
- if (!first)
- os << ", ";
- detail::print(os, a);
- first = false;
- });
- os << ")";
- } else if constexpr (is_optional_v<just_attribute>) {
- if (!attr)
- os << "<<empty>>";
- else
- detail::print(os, *attr);
- } else if constexpr (is_variant_v<just_attribute>) {
- os << "<<variant>>";
- } else {
- printer<just_attribute>{}(os, attr);
- }
- }
- template<typename Attribute>
- inline void
- print_attribute(std::ostream & os, Attribute const & attr, int indent)
- {
- detail::trace_indent(os, indent);
- os << "attribute: ";
- detail::print(os, attr);
- os << "\n";
- }
- inline void print_attribute(std::ostream &, nope const &, int) {}
- constexpr inline bool do_trace(flags f)
- {
- return (uint32_t(f) & uint32_t(flags::trace)) == uint32_t(flags::trace);
- }
- template<typename Context, typename T>
- auto resolve(Context const & context, T const & x);
- template<typename Context>
- auto resolve(Context const &, nope n);
- template<
- bool DoTrace,
- typename Iter,
- typename Sentinel,
- typename Context,
- typename Attribute>
- struct scoped_trace_t
- {
- scoped_trace_t(
- std::ostream & os,
- Iter & first,
- Sentinel last,
- Context const & context,
- flags f,
- Attribute const & attr,
- std::string name) :
- os_(os),
- initial_first_(first),
- first_(first),
- last_(last),
- context_(context),
- flags_(f),
- attr_(attr),
- name_(std::move(name))
- {
- if (!detail::do_trace(flags_))
- return;
- detail::trace_prefix(os, first_, last_, context_, name_);
- }
- ~scoped_trace_t()
- {
- if (!detail::do_trace(flags_))
- return;
- detail::trace_indent(os_, detail::_indent(context_));
- if (*context_.pass_) {
- os_ << "matched ";
- detail::trace_input(os_, initial_first_, first_);
- os_ << "\n";
- detail::print_attribute(
- os_,
- detail::resolve(context_, attr_),
- detail::_indent(context_));
- } else {
- os_ << "no match\n";
- }
- detail::trace_suffix(os_, first_, last_, context_, name_);
- }
- std::ostream & os_;
- Iter initial_first_;
- Iter & first_;
- Sentinel last_;
- Context const & context_;
- flags flags_;
- Attribute const & attr_;
- std::string name_;
- };
- template<
- typename Iter,
- typename Sentinel,
- typename Context,
- typename Attribute>
- struct scoped_trace_t<false, Iter, Sentinel, Context, Attribute>
- {
- scoped_trace_t() {}
- };
- template<
- typename Parser,
- typename Iter,
- typename Sentinel,
- typename Context,
- typename Attribute>
- auto scoped_trace(
- Parser const & parser,
- Iter & first,
- Sentinel last,
- Context const & context,
- flags f,
- Attribute const & attr)
- {
- if constexpr (Context::do_trace) {
- std::stringstream oss;
- detail::print_parser(context, parser, oss);
- std::ostream & os = BOOST_PARSER_TRACE_OSTREAM;
- return scoped_trace_t<true, Iter, Sentinel, Context, Attribute>(
- os, first, last, context, f, attr, oss.str());
- } else {
- return scoped_trace_t<false, Iter, Sentinel, Context, Attribute>{};
- }
- }
- template<typename Context, typename Attribute>
- auto final_trace(Context const & context, flags f, Attribute const & attr)
- {
- if (!detail::do_trace(f))
- return;
- std::ostream & os = BOOST_PARSER_TRACE_OSTREAM;
- os << "--------------------\n";
- if (*context.pass_) {
- os << "parse succeeded\n";
- detail::print_attribute(os, detail::resolve(context, attr), 0);
- } else {
- os << "parse failed\n";
- }
- os << "--------------------" << std::endl;
- }
- }}}
- #endif
|