Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:40:28

0001 #ifndef BOOST_PARSER_DETAIL_PRINTING_HPP
0002 #define BOOST_PARSER_DETAIL_PRINTING_HPP
0003 
0004 #include <boost/parser/parser_fwd.hpp>
0005 #include <boost/parser/tuple.hpp>
0006 #include <boost/parser/detail/detection.hpp>
0007 #include <boost/parser/detail/hl.hpp>
0008 #include <boost/parser/detail/text/unpack.hpp>
0009 #if defined(_MSC_VER) && defined(BOOST_PARSER_TRACE_TO_VS_OUTPUT)
0010 #include <boost/parser/detail/vs_output_stream.hpp>
0011 #endif
0012 #include <boost/parser/detail/text/transcode_view.hpp>
0013 
0014 #include <iomanip>
0015 #include <iostream>
0016 #include <optional>
0017 #include <sstream>
0018 #include <string>
0019 #include <variant>
0020 
0021 #include <cctype>
0022 
0023 
0024 namespace boost { namespace parser { namespace detail {
0025 
0026     template<typename Context>
0027     decltype(auto) _indent(Context const & context);
0028 
0029     template<typename Char>
0030     std::ostream & print_char(std::ostream & os, Char c)
0031     {
0032         if constexpr (
0033 #if defined(__cpp_char8_t)
0034             std::is_same_v<
0035                 char8_t,
0036                 std::remove_cv_t<std::remove_reference_t<Char>>>
0037 #else
0038             false
0039 #endif
0040         ) {
0041             os << char(c);
0042         } else {
0043             os << c;
0044         }
0045         return os;
0046     }
0047 
0048     enum { parser_component_limit = 4 };
0049 
0050     template<
0051         typename Context,
0052         typename Parser,
0053         typename DelimiterParser,
0054         typename MinType,
0055         typename MaxType>
0056     void print_parser(
0057         Context const & context,
0058         repeat_parser<Parser, DelimiterParser, MinType, MaxType> const & parser,
0059         std::ostream & os,
0060         int components = 0);
0061 
0062     template<typename Context, typename Parser>
0063     void print_parser(
0064         Context const & context,
0065         opt_parser<Parser> const & parser,
0066         std::ostream & os,
0067         int components = 0);
0068 
0069     template<typename Context, typename ParserTuple>
0070     void print_parser(
0071         Context const & context,
0072         or_parser<ParserTuple> const & parser,
0073         std::ostream & os,
0074         int components = 0);
0075 
0076     template<typename Context, typename ParserTuple, typename DelimiterParser>
0077     void print_parser(
0078         Context const & context,
0079         perm_parser<ParserTuple, DelimiterParser> const & parser,
0080         std::ostream & os,
0081         int components = 0);
0082 
0083     template<
0084         typename Context,
0085         typename ParserTuple,
0086         typename BacktrackingTuple,
0087         typename CombiningGroups>
0088     void print_parser(
0089         Context const & context,
0090         seq_parser<ParserTuple, BacktrackingTuple, CombiningGroups> const &
0091             parser,
0092         std::ostream & os,
0093         int components = 0);
0094 
0095     template<typename Context, typename Parser, typename Action>
0096     void print_parser(
0097         Context const & context,
0098         action_parser<Parser, Action> const & parser,
0099         std::ostream & os,
0100         int components = 0);
0101 
0102     template<typename Context, typename Parser, typename F>
0103     void print_parser(
0104         Context const & context,
0105         transform_parser<Parser, F> const & parser,
0106         std::ostream & os,
0107         int components = 0);
0108 
0109     template<typename Context, typename Parser>
0110     void print_parser(
0111         Context const & context,
0112         omit_parser<Parser> const & parser,
0113         std::ostream & os,
0114         int components = 0);
0115 
0116     template<typename Context, typename Parser>
0117     void print_parser(
0118         Context const & context,
0119         raw_parser<Parser> const & parser,
0120         std::ostream & os,
0121         int components = 0);
0122 
0123 #if defined(BOOST_PARSER_DOXYGEN) || BOOST_PARSER_USE_CONCEPTS
0124     template<typename Context, typename Parser>
0125     void print_parser(
0126         Context const & context,
0127         string_view_parser<Parser> const & parser,
0128         std::ostream & os,
0129         int components = 0);
0130 #endif
0131 
0132     template<typename Context, typename Parser>
0133     void print_parser(
0134         Context const & context,
0135         lexeme_parser<Parser> const & parser,
0136         std::ostream & os,
0137         int components = 0);
0138 
0139     template<typename Context, typename Parser>
0140     void print_parser(
0141         Context const & context,
0142         no_case_parser<Parser> const & parser,
0143         std::ostream & os,
0144         int components = 0);
0145 
0146     template<typename Context, typename Parser, typename SkipParser>
0147     void print_parser(
0148         Context const & context,
0149         skip_parser<Parser, SkipParser> const & parser,
0150         std::ostream & os,
0151         int components = 0);
0152 
0153     template<typename Context, typename Parser, bool FailOnMatch>
0154     void print_parser(
0155         Context const & context,
0156         expect_parser<Parser, FailOnMatch> const & parser,
0157         std::ostream & os,
0158         int components = 0);
0159 
0160     template<
0161         typename Context,
0162         bool UseCallbacks,
0163         typename Parser,
0164         typename Attribute,
0165         typename LocalState,
0166         typename ParamsTuple>
0167     void print_parser(
0168         Context const & context,
0169         rule_parser<
0170             UseCallbacks,
0171             Parser,
0172             Attribute,
0173             LocalState,
0174             ParamsTuple> const & parser,
0175         std::ostream & os,
0176         int components = 0);
0177 
0178     template<typename Context, typename T>
0179     void print_parser(
0180         Context const & context,
0181         symbol_parser<T> const & parser,
0182         std::ostream & os,
0183         int components = 0);
0184 
0185     template<typename Context, typename Predicate>
0186     void print_parser(
0187         Context const & context,
0188         eps_parser<Predicate> const & parser,
0189         std::ostream & os,
0190         int components = 0);
0191 
0192     template<typename Context>
0193     void print_parser(
0194         Context const & context,
0195         eps_parser<nope> const & parser,
0196         std::ostream & os,
0197         int components = 0);
0198 
0199     template<typename Context>
0200     void print_parser(
0201         Context const & context,
0202         eoi_parser const & parser,
0203         std::ostream & os,
0204         int components = 0);
0205 
0206     template<typename Context, typename Atribute>
0207     void print_parser(
0208         Context const & context,
0209         attr_parser<Atribute> const & parser,
0210         std::ostream & os,
0211         int components = 0);
0212 
0213     template<typename Context, typename Expected, typename AttributeType>
0214     void print_parser(
0215         Context const & context,
0216         char_parser<Expected, AttributeType> const & parser,
0217         std::ostream & os,
0218         int components = 0);
0219 
0220     template<typename Context>
0221     void print_parser(
0222         Context const & context,
0223         digit_parser const & parser,
0224         std::ostream & os,
0225         int components = 0);
0226 
0227     template<typename Context>
0228     void print_parser(
0229         Context const & context,
0230         char_subrange_parser<hex_digit_subranges> const & parser,
0231         std::ostream & os,
0232         int components = 0);
0233 
0234     template<typename Context>
0235     void print_parser(
0236         Context const & context,
0237         char_subrange_parser<control_subranges> const & parser,
0238         std::ostream & os,
0239         int components = 0);
0240 
0241     template<typename Context>
0242     void print_parser(
0243         Context const & context,
0244         char_set_parser<punct_chars> const & parser,
0245         std::ostream & os,
0246         int components = 0);
0247 
0248     template<typename Context>
0249     void print_parser(
0250         Context const & context,
0251         char_set_parser<symb_chars> const & parser,
0252         std::ostream & os,
0253         int components = 0);
0254 
0255     template<typename Context>
0256     void print_parser(
0257         Context const & context,
0258         char_set_parser<lower_case_chars> const & parser,
0259         std::ostream & os,
0260         int components = 0);
0261 
0262     template<typename Context>
0263     void print_parser(
0264         Context const & context,
0265         char_set_parser<upper_case_chars> const & parser,
0266         std::ostream & os,
0267         int components = 0);
0268 
0269     template<typename Context, typename Expected, typename AttributeType>
0270     void print_parser(
0271         Context const & context,
0272         omit_parser<char_parser<Expected, AttributeType>> const & parser,
0273         std::ostream & os,
0274         int components = 0);
0275 
0276     template<typename Context, typename StrIter, typename StrSentinel>
0277     void print_parser(
0278         Context const & context,
0279         string_parser<StrIter, StrSentinel> const & parser,
0280         std::ostream & os,
0281         int components = 0);
0282 
0283     template<typename Context, typename StrIter, typename StrSentinel>
0284     void print_parser(
0285         Context const & context,
0286         omit_parser<string_parser<StrIter, StrSentinel>> const & parser,
0287         std::ostream & os,
0288         int components = 0);
0289 
0290     template<
0291         typename Context,
0292         typename Quotes,
0293         typename Escapes,
0294         typename CharParser>
0295     void print_parser(
0296         Context const & context,
0297         quoted_string_parser<Quotes, Escapes, CharParser> const & parser,
0298         std::ostream & os,
0299         int components = 0);
0300 
0301     template<typename Context, bool NewlinesOnly, bool NoNewlines>
0302     void print_parser(
0303         Context const & context,
0304         ws_parser<NewlinesOnly, NoNewlines> const & parser,
0305         std::ostream & os,
0306         int components = 0);
0307 
0308     template<typename Context>
0309     void print_parser(
0310         Context const & context,
0311         bool_parser const & parser,
0312         std::ostream & os,
0313         int components = 0);
0314 
0315     template<
0316         typename Context,
0317         typename T,
0318         int Radix,
0319         int MinDigits,
0320         int MaxDigits,
0321         typename Expected>
0322     void print_parser(
0323         Context const & context,
0324         uint_parser<T, Radix, MinDigits, MaxDigits, Expected> const & parser,
0325         std::ostream & os,
0326         int components = 0);
0327 
0328     template<
0329         typename Context,
0330         typename T,
0331         int Radix,
0332         int MinDigits,
0333         int MaxDigits,
0334         typename Expected>
0335     void print_parser(
0336         Context const & context,
0337         int_parser<T, Radix, MinDigits, MaxDigits, Expected> const & parser,
0338         std::ostream & os,
0339         int components = 0);
0340 
0341     template<typename Context, typename T>
0342     void print_parser(
0343         Context const & context,
0344         float_parser<T> const & parser,
0345         std::ostream & os,
0346         int components = 0);
0347 
0348     template<typename Context>
0349     void print_parser(
0350         Context const & context,
0351         float_parser<float> const & parser,
0352         std::ostream & os,
0353         int components = 0);
0354 
0355     template<typename Context>
0356     void print_parser(
0357         Context const & context,
0358         float_parser<double> const & parser,
0359         std::ostream & os,
0360         int components = 0);
0361 
0362     template<typename Context, typename SwitchValue, typename OrParser>
0363     void print_parser(
0364         Context const & context,
0365         switch_parser<SwitchValue, OrParser> const & parser,
0366         std::ostream & os,
0367         int components = 0);
0368 
0369     enum { trace_indent_factor = 2 };
0370 
0371     inline void trace_indent(std::ostream & os, int indent)
0372     {
0373         for (int i = 0, end = trace_indent_factor * indent; i != end; ++i) {
0374             os << ' ';
0375         }
0376     }
0377 
0378     template<typename Iter, typename Sentinel, int SizeofValueType>
0379     struct trace_input_impl
0380     {
0381         static void call(
0382             std::ostream & os,
0383             Iter first_,
0384             Sentinel last_,
0385             bool quote,
0386             int64_t trace_input_cps)
0387         {
0388             auto utf8 = BOOST_PARSER_DETAIL_TEXT_SUBRANGE(first_, last_) | text::as_utf8;
0389             auto first = utf8.begin();
0390             auto last = utf8.end();
0391             if (quote)
0392                 os << '"';
0393             for (int64_t i = 0; i < trace_input_cps && first != last;
0394                  ++i, ++first) {
0395                 detail::print_char(os, *first);
0396             }
0397             if (quote)
0398                 os << '"';
0399         }
0400     };
0401 
0402     template<typename Iter, typename Sentinel>
0403     struct trace_input_impl<Iter, Sentinel, 1>
0404     {
0405         static void call(
0406             std::ostream & os,
0407             Iter first_,
0408             Sentinel last_,
0409             bool quote,
0410             int64_t trace_input_cps)
0411         {
0412             auto r = BOOST_PARSER_DETAIL_TEXT_SUBRANGE(first_, last_);
0413             auto r_unpacked =
0414                 detail::text::unpack_iterator_and_sentinel(first_, last_);
0415             auto utf32 = r | text::as_utf32;
0416             auto first = utf32.begin();
0417             auto const last = utf32.end();
0418             for (int64_t i = 0; i < trace_input_cps && first != last; ++i) {
0419                 ++first;
0420             }
0421             if (quote)
0422                 os << '"';
0423             auto first_repacked = r_unpacked.repack(first.base());
0424             for (Iter it = first_, end = first_repacked; it != end; ++it) {
0425                 detail::print_char(os, *it);
0426             }
0427             if (quote)
0428                 os << '"';
0429         }
0430     };
0431 
0432     template<typename Iter, typename Sentinel>
0433     inline void trace_input(
0434         std::ostream & os,
0435         Iter first,
0436         Sentinel last,
0437         bool quote = true,
0438         int64_t trace_input_cps = 8)
0439     {
0440         trace_input_impl<Iter, Sentinel, sizeof(*first)>::call(
0441             os, first, last, quote, trace_input_cps);
0442     }
0443 
0444     template<typename Iter, typename Sentinel>
0445     inline void trace_begin_match(
0446         std::ostream & os,
0447         Iter first,
0448         Sentinel last,
0449         int indent,
0450         std::string_view name)
0451     {
0452         detail::trace_indent(os, indent);
0453         os << "[begin " << name << "; input=";
0454         detail::trace_input(os, first, last);
0455         os << "]" << std::endl;
0456     }
0457 
0458     template<typename Iter, typename Sentinel>
0459     inline void trace_end_match(
0460         std::ostream & os,
0461         Iter first,
0462         Sentinel last,
0463         int indent,
0464         std::string_view name)
0465     {
0466         detail::trace_indent(os, indent);
0467         os << "[end " << name << "; input=";
0468         detail::trace_input(os, first, last);
0469         os << "]" << std::endl;
0470     }
0471 
0472     template<typename Iter, typename Sentinel, typename Context>
0473     void trace_prefix(
0474         std::ostream & os,
0475         Iter first,
0476         Sentinel last,
0477         Context const & context,
0478         std::string_view name)
0479     {
0480         int & indent = detail::_indent(context);
0481         detail::trace_begin_match(os, first, last, indent, name);
0482         ++indent;
0483     }
0484 
0485     template<typename Iter, typename Sentinel, typename Context>
0486     void trace_suffix(
0487         std::ostream & os,
0488         Iter first,
0489         Sentinel last,
0490         Context const & context,
0491         std::string_view name)
0492     {
0493         int & indent = detail::_indent(context);
0494         --indent;
0495         detail::trace_end_match(os, first, last, indent, name);
0496     }
0497 
0498     template<typename T>
0499     using streamable =
0500         decltype(std::declval<std::ostream &>() << std::declval<T const &>());
0501 
0502     template<typename T, bool Streamable = is_detected_v<streamable, T>>
0503     struct printer
0504     {
0505         std::ostream & operator()(std::ostream & os, T const &)
0506         {
0507             return os << "<<unprintable-value>>";
0508         }
0509     };
0510 
0511     template<typename T>
0512     void print_printable(std::ostream & os, T const & x)
0513     {
0514         os << x;
0515     }
0516 
0517     inline void print_printable(std::ostream & os, char c)
0518     {
0519         if (std::isprint(c)) {
0520             os << "'" << c << "'";
0521         } else {
0522             unsigned char c_ = c;
0523             os << "'\\x" << std::hex << std::setfill('0') << (uint32_t)c_
0524                << "'";
0525         }
0526     }
0527 
0528     inline void print_printable(std::ostream & os, char32_t c)
0529     {
0530         if (c < 256) {
0531             os << "U";
0532             detail::print_printable(os, (char)c);
0533         } else {
0534             os << "U'\\U" << std::hex << std::setfill('0') << (int32_t)c << "'";
0535         }
0536     }
0537 
0538     template<typename T>
0539     struct printer<T, true>
0540     {
0541         std::ostream & operator()(std::ostream & os, T const & x)
0542         {
0543             detail::print_printable(os, x);
0544             return os;
0545         }
0546     };
0547 
0548     template<typename T>
0549     constexpr bool is_variant_v = enable_variant<T>;
0550 
0551     template<typename Attribute>
0552     inline void print(std::ostream & os, Attribute const & attr)
0553     {
0554         using just_attribute =
0555             std::remove_cv_t<std::remove_reference_t<Attribute>>;
0556         if constexpr (is_tuple<just_attribute>{}) {
0557             os << "(";
0558             bool first = true;
0559             hl::for_each(attr, [&](auto const & a) {
0560                 if (!first)
0561                     os << ", ";
0562                 detail::print(os, a);
0563                 first = false;
0564             });
0565             os << ")";
0566         } else if constexpr (is_optional_v<just_attribute>) {
0567             if (!attr)
0568                 os << "<<empty>>";
0569             else
0570                 detail::print(os, *attr);
0571         } else if constexpr (is_variant_v<just_attribute>) {
0572             os << "<<variant>>";
0573         } else {
0574             printer<just_attribute>{}(os, attr);
0575         }
0576     }
0577 
0578     template<typename Attribute>
0579     inline void
0580     print_attribute(std::ostream & os, Attribute const & attr, int indent)
0581     {
0582         detail::trace_indent(os, indent);
0583         os << "attribute: ";
0584         detail::print(os, attr);
0585         os << "\n";
0586     }
0587 
0588     inline void print_attribute(std::ostream &, nope const &, int) {}
0589 
0590     constexpr inline bool do_trace(flags f)
0591     {
0592         return (uint32_t(f) & uint32_t(flags::trace)) == uint32_t(flags::trace);
0593     }
0594 
0595     template<typename Context, typename T>
0596     auto resolve(Context const & context, T const & x);
0597 
0598     template<typename Context>
0599     auto resolve(Context const &, nope n);
0600 
0601     template<
0602         bool DoTrace,
0603         typename Iter,
0604         typename Sentinel,
0605         typename Context,
0606         typename Attribute>
0607     struct scoped_trace_t
0608     {
0609         scoped_trace_t(
0610             std::ostream & os,
0611             Iter & first,
0612             Sentinel last,
0613             Context const & context,
0614             flags f,
0615             Attribute const & attr,
0616             std::string name) :
0617             os_(os),
0618             initial_first_(first),
0619             first_(first),
0620             last_(last),
0621             context_(context),
0622             flags_(f),
0623             attr_(attr),
0624             name_(std::move(name))
0625         {
0626             if (!detail::do_trace(flags_))
0627                 return;
0628             detail::trace_prefix(os, first_, last_, context_, name_);
0629         }
0630 
0631         ~scoped_trace_t()
0632         {
0633             if (!detail::do_trace(flags_))
0634                 return;
0635             detail::trace_indent(os_, detail::_indent(context_));
0636             if (*context_.pass_) {
0637                 os_ << "matched ";
0638                 detail::trace_input(os_, initial_first_, first_);
0639                 os_ << "\n";
0640                 detail::print_attribute(
0641                     os_,
0642                     detail::resolve(context_, attr_),
0643                     detail::_indent(context_));
0644             } else {
0645                 os_ << "no match\n";
0646             }
0647             detail::trace_suffix(os_, first_, last_, context_, name_);
0648         }
0649 
0650         std::ostream & os_;
0651         Iter initial_first_;
0652         Iter & first_;
0653         Sentinel last_;
0654         Context const & context_;
0655         flags flags_;
0656         Attribute const & attr_;
0657         std::string name_;
0658     };
0659 
0660     template<
0661         typename Iter,
0662         typename Sentinel,
0663         typename Context,
0664         typename Attribute>
0665     struct scoped_trace_t<false, Iter, Sentinel, Context, Attribute>
0666     {
0667         scoped_trace_t() {}
0668     };
0669 
0670     template<
0671         typename Parser,
0672         typename Iter,
0673         typename Sentinel,
0674         typename Context,
0675         typename Attribute>
0676     auto scoped_trace(
0677         Parser const & parser,
0678         Iter & first,
0679         Sentinel last,
0680         Context const & context,
0681         flags f,
0682         Attribute const & attr)
0683     {
0684         if constexpr (Context::do_trace) {
0685             std::stringstream oss;
0686             detail::print_parser(context, parser, oss);
0687             std::ostream & os = BOOST_PARSER_TRACE_OSTREAM;
0688             return scoped_trace_t<true, Iter, Sentinel, Context, Attribute>(
0689                 os, first, last, context, f, attr, oss.str());
0690         } else {
0691             return scoped_trace_t<false, Iter, Sentinel, Context, Attribute>{};
0692         }
0693     }
0694 
0695     template<typename Context, typename Attribute>
0696     auto final_trace(Context const & context, flags f, Attribute const & attr)
0697     {
0698         if (!detail::do_trace(f))
0699             return;
0700 
0701         std::ostream & os = BOOST_PARSER_TRACE_OSTREAM;
0702         os << "--------------------\n";
0703         if (*context.pass_) {
0704             os << "parse succeeded\n";
0705             detail::print_attribute(os, detail::resolve(context, attr), 0);
0706         } else {
0707             os << "parse failed\n";
0708         }
0709         os << "--------------------" << std::endl;
0710     }
0711 
0712 }}}
0713 
0714 #endif