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_IMPL_HPP
0002 #define BOOST_PARSER_DETAIL_PRINTING_IMPL_HPP
0003 
0004 #include <boost/parser/detail/printing.hpp>
0005 
0006 #if __has_include(<boost/type_index.hpp>)
0007 #if defined(__GNUC__) || defined(__clang__)
0008 #pragma GCC diagnostic push
0009 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
0010 #endif
0011 #include <boost/type_index.hpp>
0012 #define BOOST_PARSER_HAVE_BOOST_TYPEINDEX 1
0013 #define BOOST_PARSER_TYPE_NAME_NS boost_type_index
0014 #if defined(__GNUC__) || defined(__clang__)
0015 #pragma GCC diagnostic pop
0016 #endif
0017 #else
0018 #include <typeinfo>
0019 #define BOOST_PARSER_HAVE_BOOST_TYPEINDEX 0
0020 #define BOOST_PARSER_TYPE_NAME_NS std_typeinfo
0021 #endif
0022 
0023 
0024 namespace boost { namespace parser { namespace detail {
0025 
0026     inline namespace BOOST_PARSER_TYPE_NAME_NS {
0027         template<typename T>
0028         auto type_name()
0029         {
0030 #if BOOST_PARSER_HAVE_BOOST_TYPEINDEX
0031             return typeindex::type_id<T>().pretty_name();
0032 #else
0033             return typeid(T).name();
0034 #endif
0035         }
0036     }
0037 
0038     template<typename Parser>
0039     struct n_aray_parser : std::false_type
0040     {};
0041 
0042     template<
0043         typename Parser,
0044         typename DelimiterParser,
0045         typename MinType,
0046         typename MaxType>
0047     struct n_aray_parser<
0048         repeat_parser<Parser, DelimiterParser, MinType, MaxType>>
0049         : std::true_type
0050     {};
0051 
0052     template<typename Parser, typename MinType, typename MaxType>
0053     struct n_aray_parser<repeat_parser<Parser, detail::nope, MinType, MaxType>>
0054         : std::false_type
0055     {};
0056 
0057     template<typename Parser, typename DelimiterParser>
0058     struct n_aray_parser<delimited_seq_parser<Parser, DelimiterParser>>
0059         : std::true_type
0060     {};
0061 
0062     template<typename ParserTuple>
0063     struct n_aray_parser<or_parser<ParserTuple>> : std::true_type
0064     {};
0065 
0066     template<typename ParserTuple, typename DelimiterParser>
0067     struct n_aray_parser<perm_parser<ParserTuple, DelimiterParser>>
0068         : std::true_type
0069     {};
0070 
0071     template<
0072         typename ParserTuple,
0073         typename BacktrackingTuple,
0074         typename CombiningGroups>
0075     struct n_aray_parser<
0076         seq_parser<ParserTuple, BacktrackingTuple, CombiningGroups>>
0077         : std::true_type
0078     {};
0079 
0080     // true iff Parser is an n-ary parser (contains N>2 subparsers).
0081     template<typename Parser>
0082     constexpr bool n_aray_parser_v = n_aray_parser<Parser>::value;
0083 
0084     template<typename Context, typename Expected>
0085     void print_expected(
0086         Context const & context,
0087         std::ostream & os,
0088         Expected expected,
0089         bool no_parens = false)
0090     {
0091         if (is_nope_v<Expected>)
0092             return;
0093         if (!no_parens)
0094             os << "(";
0095         detail::print(os, detail::resolve(context, expected));
0096         if (!no_parens)
0097             os << ")";
0098     }
0099 
0100     template<
0101         typename Context,
0102         typename Parser,
0103         typename DelimiterParser,
0104         typename MinType,
0105         typename MaxType>
0106     void print_parser(
0107         Context const & context,
0108         repeat_parser<Parser, DelimiterParser, MinType, MaxType> const & parser,
0109         std::ostream & os,
0110         int components)
0111     {
0112         if constexpr (is_nope_v<DelimiterParser>) {
0113             auto const min_ = detail::resolve(context, parser.min_);
0114             auto const max_ = detail::resolve(context, parser.max_);
0115             constexpr bool n_ary_child = n_aray_parser_v<Parser>;
0116             if (min_ == 0 && max_ == Inf) {
0117                 os << "*";
0118                 if (n_ary_child)
0119                     os << "(";
0120                 detail::print_parser(
0121                     context, parser.parser_, os, components + 1);
0122                 if (n_ary_child)
0123                     os << ")";
0124             } else if (min_ == 1 && max_ == Inf) {
0125                 os << "+";
0126                 if (n_ary_child)
0127                     os << "(";
0128                 detail::print_parser(
0129                     context, parser.parser_, os, components + 1);
0130                 if (n_ary_child)
0131                     os << ")";
0132             } else {
0133                 os << "repeat(";
0134                 detail::print(os, min_);
0135                 if (min_ == max_) {
0136                     os << ")[";
0137                 } else {
0138                     os << ", ";
0139                     if (max_ == unbounded)
0140                         os << "Inf";
0141                     else
0142                         detail::print(os, max_);
0143                     os << ")[";
0144                 }
0145                 detail::print_parser(
0146                     context, parser.parser_, os, components + 1);
0147                 os << "]";
0148             }
0149         } else {
0150             detail::print_parser(context, parser.parser_, os, components + 1);
0151             os << " % ";
0152             detail::print_parser(
0153                 context, parser.delimiter_parser_, os, components + 2);
0154         }
0155     }
0156 
0157     template<typename Context, typename Parser>
0158     void print_parser(
0159         Context const & context,
0160         opt_parser<Parser> const & parser,
0161         std::ostream & os,
0162         int components)
0163     {
0164         os << "-";
0165         constexpr bool n_ary_child = n_aray_parser_v<Parser>;
0166         if (n_ary_child)
0167             os << "(";
0168         detail::print_parser(context, parser.parser_, os, components + 1);
0169         if (n_ary_child)
0170             os << ")";
0171     }
0172 
0173     template<typename Context, typename Parser>
0174     void print_or_like_parser(
0175         Context const & context,
0176         Parser const & parser,
0177         std::ostream & os,
0178         int components,
0179         std::string_view or_ellipsis,
0180         std::string_view ws_or)
0181     {
0182         int i = 0;
0183         bool printed_ellipsis = false;
0184         hl::for_each(parser.parsers_, [&](auto const & parser) {
0185             if (components == parser_component_limit) {
0186                 if (!printed_ellipsis)
0187                     os << or_ellipsis;
0188                 printed_ellipsis = true;
0189                 return;
0190             }
0191             if (i)
0192                 os << ws_or;
0193             detail::print_parser(context, parser, os, components);
0194             ++components;
0195             ++i;
0196         });
0197     }
0198 
0199     template<typename Context, typename ParserTuple>
0200     void print_parser(
0201         Context const & context,
0202         or_parser<ParserTuple> const & parser,
0203         std::ostream & os,
0204         int components)
0205     {
0206         detail::print_or_like_parser(
0207             context, parser, os, components, " | ...", " | ");
0208     }
0209 
0210     template<typename Context, typename ParserTuple, typename DelimiterParser>
0211     void print_parser(
0212         Context const & context,
0213         perm_parser<ParserTuple, DelimiterParser> const & parser,
0214         std::ostream & os,
0215         int components)
0216     {
0217         if constexpr (!is_nope_v<DelimiterParser>) {
0218             os << "delimiter(";
0219             detail::print_parser(
0220                 context, parser.delimiter_parser_, os, components);
0221             os << ")[";
0222         }
0223         detail::print_or_like_parser(
0224             context, parser, os, components, " || ...", " || ");
0225         if constexpr (!is_nope_v<DelimiterParser>)
0226             os << "]";
0227     }
0228 
0229     template<
0230         typename Context,
0231         typename ParserTuple,
0232         typename BacktrackingTuple,
0233         typename CombiningGroups>
0234     void print_parser(
0235         Context const & context,
0236         seq_parser<ParserTuple, BacktrackingTuple, CombiningGroups> const &
0237             parser,
0238         std::ostream & os,
0239         int components)
0240     {
0241         int prev_group = 0;
0242         int i = 0;
0243         bool printed_ellipsis = false;
0244         using combining_groups =
0245             detail::combining_t<ParserTuple, CombiningGroups>;
0246         hl::for_each(
0247             hl::zip(parser.parsers_, BacktrackingTuple{}, combining_groups{}),
0248             [&](auto const & parser_and_backtrack) {
0249                 using namespace literals;
0250                 auto const & parser = parser::get(parser_and_backtrack, 0_c);
0251                 auto const backtrack = parser::get(parser_and_backtrack, 1_c);
0252                 auto const group = parser::get(parser_and_backtrack, 2_c);
0253 
0254                 if (components == parser_component_limit) {
0255                     if (!printed_ellipsis) {
0256                         os << (backtrack ? " >> ..." : " > ...");
0257                     }
0258                     printed_ellipsis = true;
0259                     return;
0260                 }
0261                 if (group != prev_group && prev_group)
0262                     os << ']';
0263                 if (i)
0264                     os << (backtrack ? " >> " : " > ");
0265                 if (group != prev_group && group)
0266                     os << (group == -1 ? "separate[" : "merge[");
0267                 detail::print_parser(context, parser, os, components);
0268                 ++components;
0269                 ++i;
0270                 prev_group = (int)group;
0271             });
0272         if (prev_group && !printed_ellipsis)
0273             os << ']';
0274     }
0275 
0276     template<typename Context, typename Parser, typename Action>
0277     void print_parser(
0278         Context const & context,
0279         action_parser<Parser, Action> const & parser,
0280         std::ostream & os,
0281         int components)
0282     {
0283         detail::print_parser(context, parser.parser_, os, components);
0284         os << "[<<action>>]";
0285     }
0286 
0287     template<typename Context, typename Parser>
0288     void print_directive(
0289         Context const & context,
0290         std::string_view name,
0291         Parser const & parser,
0292         std::ostream & os,
0293         int components)
0294     {
0295         os << name << "[";
0296         if (++components == parser_component_limit)
0297             os << "...";
0298         else
0299             detail::print_parser(context, parser, os, components + 1);
0300         os << "]";
0301     }
0302 
0303     template<typename Context, typename Parser, typename F>
0304     void print_parser(
0305         Context const & context,
0306         transform_parser<Parser, F> const & parser,
0307         std::ostream & os,
0308         int components)
0309     {
0310         detail::print_directive(
0311             context, "transform(<<f>>)", parser.parser_, os, components);
0312     }
0313 
0314     template<typename Context, typename Parser>
0315     void print_parser(
0316         Context const & context,
0317         omit_parser<Parser> const & parser,
0318         std::ostream & os,
0319         int components)
0320     {
0321         detail::print_directive(
0322             context, "omit", parser.parser_, os, components);
0323     }
0324 
0325     template<typename Context, typename Parser>
0326     void print_parser(
0327         Context const & context,
0328         raw_parser<Parser> const & parser,
0329         std::ostream & os,
0330         int components)
0331     {
0332         detail::print_directive(context, "raw", parser.parser_, os, components);
0333     }
0334 
0335 #if defined(BOOST_PARSER_DOXYGEN) || BOOST_PARSER_USE_CONCEPTS
0336     template<typename Context, typename Parser>
0337     void print_parser(
0338         Context const & context,
0339         string_view_parser<Parser> const & parser,
0340         std::ostream & os,
0341         int components)
0342     {
0343         detail::print_directive(
0344             context, "string_view", parser.parser_, os, components);
0345     }
0346 #endif
0347 
0348     template<typename Context, typename Parser>
0349     void print_parser(
0350         Context const & context,
0351         lexeme_parser<Parser> const & parser,
0352         std::ostream & os,
0353         int components)
0354     {
0355         detail::print_directive(
0356             context, "lexeme", parser.parser_, os, components);
0357     }
0358 
0359     template<typename Context, typename Parser>
0360     void print_parser(
0361         Context const & context,
0362         no_case_parser<Parser> const & parser,
0363         std::ostream & os,
0364         int components)
0365     {
0366         detail::print_directive(
0367             context, "no_case", parser.parser_, os, components);
0368     }
0369 
0370     template<typename Context, typename Parser, typename SkipParser>
0371     void print_parser(
0372         Context const & context,
0373         skip_parser<Parser, SkipParser> const & parser,
0374         std::ostream & os,
0375         int components)
0376     {
0377         if constexpr (is_nope_v<SkipParser>) {
0378             detail::print_directive(
0379                 context, "skip", parser.parser_, os, components);
0380         } else {
0381             os << "skip(";
0382             detail::print_parser(
0383                 context, parser.skip_parser_.parser_, os, components);
0384             os << ")";
0385             detail::print_directive(
0386                 context, "", parser.parser_, os, components + 1);
0387         }
0388     }
0389 
0390     template<typename Context, typename Parser, bool FailOnMatch>
0391     void print_parser(
0392         Context const & context,
0393         expect_parser<Parser, FailOnMatch> const & parser,
0394         std::ostream & os,
0395         int components)
0396     {
0397         if (FailOnMatch)
0398             os << "!";
0399         else
0400             os << "&";
0401         constexpr bool n_ary_child = n_aray_parser_v<Parser>;
0402         if (n_ary_child)
0403             os << "(";
0404         detail::print_parser(context, parser.parser_, os, components + 1);
0405         if (n_ary_child)
0406             os << ")";
0407     }
0408 
0409     template<
0410         typename Context,
0411         bool UseCallbacks,
0412         typename Parser,
0413         typename Attribute,
0414         typename LocalState,
0415         typename ParamsTuple>
0416     void print_parser(
0417         Context const & context,
0418         rule_parser<
0419             UseCallbacks,
0420             Parser,
0421             Attribute,
0422             LocalState,
0423             ParamsTuple> const & parser,
0424         std::ostream & os,
0425         int components)
0426     {
0427         os << parser.diagnostic_text_;
0428         if constexpr (!is_nope_v<ParamsTuple>) {
0429             os << ".with(";
0430             int i = 0;
0431             hl::for_each(parser.params_, [&](auto const & param) {
0432                 if (i++)
0433                     os << ", ";
0434                 detail::print_expected(context, os, param, true);
0435             });
0436             os << ")";
0437         }
0438     }
0439 
0440     template<typename Context, typename T>
0441     void print_parser(
0442         Context const & context,
0443         symbol_parser<T> const & parser,
0444         std::ostream & os,
0445         int components)
0446     {
0447         if (parser.diagnostic_text_.empty())
0448             os << "symbols<" << detail::type_name<T>() << ">";
0449         else
0450             os << parser.diagnostic_text_;
0451     }
0452 
0453     template<typename Context, typename Predicate>
0454     void print_parser(
0455         Context const & context,
0456         eps_parser<Predicate> const & parser,
0457         std::ostream & os,
0458         int components)
0459     {
0460         os << "eps(<<pred>>)";
0461     }
0462 
0463     template<typename Context>
0464     void print_parser(
0465         Context const & context,
0466         eps_parser<nope> const & parser,
0467         std::ostream & os,
0468         int components)
0469     {
0470         os << "eps";
0471     }
0472 
0473     template<typename Context>
0474     void print_parser(
0475         Context const & context,
0476         eoi_parser const & parser,
0477         std::ostream & os,
0478         int components)
0479     {
0480         os << "eoi";
0481     }
0482 
0483     template<typename Context, typename Atribute>
0484     void print_parser(
0485         Context const & context,
0486         attr_parser<Atribute> const & parser,
0487         std::ostream & os,
0488         int components)
0489     {
0490         os << "attr";
0491         detail::print_expected(context, os, parser.attr_);
0492     }
0493 
0494     template<
0495         typename Context,
0496         typename ResolvedExpected,
0497         bool Integral = std::is_integral<ResolvedExpected>{}>
0498     struct print_expected_char_impl
0499     {
0500         static void call(
0501             Context const & context,
0502             std::ostream & os,
0503             ResolvedExpected expected)
0504         {
0505             detail::print(os, expected);
0506         }
0507     };
0508 
0509     template<typename Context>
0510     struct print_expected_char_impl<Context, char32_t, true>
0511     {
0512         static void
0513         call(Context const & context, std::ostream & os, char32_t expected)
0514         {
0515             if (expected == '\'') {
0516                 os << "'\\''";
0517                 return;
0518             }
0519             std::array<char32_t, 1> cps = {{expected}};
0520             auto const r = cps | text::as_utf8;
0521             os << "'";
0522             for (auto c : r) {
0523                 detail::print_char(os, c);
0524             }
0525             os << "'";
0526         }
0527     };
0528 
0529     template<typename Context, typename Expected>
0530     void print_expected_char(
0531         Context const & context, std::ostream & os, Expected expected)
0532     {
0533         auto resolved_expected = detail::resolve(context, expected);
0534         detail::print_expected_char_impl<Context, decltype(resolved_expected)>::
0535             call(context, os, resolved_expected);
0536     }
0537 
0538     template<typename Context, typename T>
0539     struct char_print_parser_impl
0540     {
0541         static void call(Context const & context, std::ostream & os, T expected)
0542         {
0543             detail::print_expected_char(context, os, expected);
0544         }
0545     };
0546 
0547     template<typename Context, typename T, typename U>
0548     struct char_print_parser_impl<Context, char_pair<T, U>>
0549     {
0550         static void call(
0551             Context const & context,
0552             std::ostream & os,
0553             char_pair<T, U> expected)
0554         {
0555             detail::print_expected_char(context, os, expected.lo_);
0556             os << ", ";
0557             detail::print_expected_char(context, os, expected.hi_);
0558         }
0559     };
0560 
0561     template<typename Context, typename Iter, typename Sentinel, bool B>
0562     struct char_print_parser_impl<Context, char_range<Iter, Sentinel, B>>
0563     {
0564         static void call(
0565             Context const & context,
0566             std::ostream & os,
0567             char_range<Iter, Sentinel, B> expected)
0568         {
0569             os << "\"";
0570             auto const r = expected.chars_ | text::as_utf8;
0571             for (auto c : r) {
0572                 detail::print_char(os, c);
0573             }
0574             os << "\"";
0575         }
0576     };
0577 
0578     template<typename Context, typename Expected, typename AttributeType>
0579     void print_parser(
0580         Context const & context,
0581         char_parser<Expected, AttributeType> const & parser,
0582         std::ostream & os,
0583         int components)
0584     {
0585         if (std::is_same_v<AttributeType, uint32_t>)
0586             os << "cp";
0587         else if (std::is_same_v<AttributeType, char>)
0588             os << "cu";
0589         else
0590             os << "char_";
0591         if constexpr (!is_nope_v<Expected>) {
0592             os << "(";
0593             char_print_parser_impl<Context, Expected>::call(
0594                 context, os, parser.expected_);
0595             os << ")";
0596         }
0597     }
0598 
0599     template<typename Context>
0600     void print_parser(
0601         Context const & context,
0602         digit_parser const & parser,
0603         std::ostream & os,
0604         int components)
0605     {
0606         os << "digit";
0607     }
0608 
0609     template<typename Context>
0610     void print_parser(
0611         Context const & context,
0612         char_subrange_parser<hex_digit_subranges> const & parser,
0613         std::ostream & os,
0614         int components)
0615     {
0616         os << "hex_digit";
0617     }
0618 
0619     template<typename Context>
0620     void print_parser(
0621         Context const & context,
0622         char_subrange_parser<control_subranges> const & parser,
0623         std::ostream & os,
0624         int components)
0625     {
0626         os << "control";
0627     }
0628 
0629     template<typename Context>
0630     void print_parser(
0631         Context const & context,
0632         char_set_parser<punct_chars> const & parser,
0633         std::ostream & os,
0634         int components)
0635     {
0636         os << "punct";
0637     }
0638 
0639     template<typename Context>
0640     void print_parser(
0641         Context const & context,
0642         char_set_parser<symb_chars> const & parser,
0643         std::ostream & os,
0644         int components)
0645     {
0646         os << "symb";
0647     }
0648 
0649     template<typename Context>
0650     void print_parser(
0651         Context const & context,
0652         char_set_parser<lower_case_chars> const & parser,
0653         std::ostream & os,
0654         int components)
0655     {
0656         os << "lower";
0657     }
0658 
0659     template<typename Context>
0660     void print_parser(
0661         Context const & context,
0662         char_set_parser<upper_case_chars> const & parser,
0663         std::ostream & os,
0664         int components)
0665     {
0666         os << "upper";
0667     }
0668 
0669     template<typename Context, typename Expected, typename AttributeType>
0670     void print_parser(
0671         Context const & context,
0672         omit_parser<char_parser<Expected, AttributeType>> const & parser,
0673         std::ostream & os,
0674         int components)
0675     {
0676         if constexpr (is_nope_v<Expected>) {
0677             os << "omit[char_]";
0678         } else {
0679             char_print_parser_impl<Context, Expected>::call(
0680                 context, os, parser.parser_.expected_);
0681         }
0682     }
0683 
0684     template<typename Context, typename StrIter, typename StrSentinel>
0685     void print_parser(
0686         Context const & context,
0687         string_parser<StrIter, StrSentinel> const & parser,
0688         std::ostream & os,
0689         int components)
0690     {
0691         os << "string(\"";
0692         for (auto c : BOOST_PARSER_DETAIL_TEXT_SUBRANGE(
0693                           parser.expected_first_, parser.expected_last_) |
0694                           text::as_utf8) {
0695             detail::print_char(os, c);
0696         }
0697         os << "\")";
0698     }
0699 
0700     template<typename Context, typename StrIter, typename StrSentinel>
0701     void print_parser(
0702         Context const & context,
0703         omit_parser<string_parser<StrIter, StrSentinel>> const & parser,
0704         std::ostream & os,
0705         int components)
0706     {
0707         os << "\"";
0708         for (auto c : BOOST_PARSER_DETAIL_TEXT_SUBRANGE(
0709                           parser.parser_.expected_first_,
0710                           parser.parser_.expected_last_) |
0711                           text::as_utf8) {
0712             detail::print_char(os, c);
0713         }
0714         os << "\"";
0715     }
0716 
0717     template<
0718         typename Context,
0719         typename Quotes,
0720         typename Escapes,
0721         typename CharParser>
0722     void print_parser(
0723         Context const & context,
0724         quoted_string_parser<Quotes, Escapes, CharParser> const & parser,
0725         std::ostream & os,
0726         int components)
0727     {
0728         os << "quoted_string(";
0729         if constexpr (is_nope_v<Quotes>) {
0730             detail::print_expected_char_impl<Context, char32_t>::call(
0731                 context, os, parser.ch_);
0732         } else {
0733             os << '"';
0734             for (auto c : parser.chs_ | text::as_utf8) {
0735                 detail::print_char(os, c);
0736             }
0737             os << '"';
0738         }
0739         os << ')';
0740     }
0741 
0742     template<typename Context, bool NewlinesOnly, bool NoNewlines>
0743     void print_parser(
0744         Context const & context,
0745         ws_parser<NewlinesOnly, NoNewlines> const & parser,
0746         std::ostream & os,
0747         int components)
0748     {
0749         if constexpr (NoNewlines)
0750             os << "blank";
0751         else if constexpr (NewlinesOnly)
0752             os << "eol";
0753         else
0754             os << "ws";
0755     }
0756 
0757     template<typename Context>
0758     void print_parser(
0759         Context const & context,
0760         bool_parser const & parser,
0761         std::ostream & os,
0762         int components)
0763     {
0764         os << "bool_";
0765     }
0766 
0767     template<
0768         typename Context,
0769         typename T,
0770         int Radix,
0771         int MinDigits,
0772         int MaxDigits,
0773         typename Expected>
0774     void print_parser(
0775         Context const & context,
0776         uint_parser<T, Radix, MinDigits, MaxDigits, Expected> const & parser,
0777         std::ostream & os,
0778         int components)
0779     {
0780         if (MinDigits == 1 && MaxDigits == -1) {
0781             if (std::is_same_v<T, unsigned short>) {
0782                 os << "ushort_";
0783                 detail::print_expected(context, os, parser.expected_);
0784                 return;
0785             } else if (std::is_same_v<T, unsigned int>) {
0786                 if (Radix == 2)
0787                     os << "bin";
0788                 else if (Radix == 8)
0789                     os << "oct";
0790                 else if (Radix == 16)
0791                     os << "hex";
0792                 else if (Radix == 10)
0793                     os << "uint_";
0794                 detail::print_expected(context, os, parser.expected_);
0795                 return;
0796             } else if (Radix == 10 && std::is_same_v<T, unsigned long>) {
0797                 os << "ulong_";
0798                 detail::print_expected(context, os, parser.expected_);
0799                 return;
0800             } else if (Radix == 10 && std::is_same_v<T, unsigned long long>) {
0801                 os << "ulong_long";
0802                 detail::print_expected(context, os, parser.expected_);
0803                 return;
0804             }
0805         }
0806         os << "uint<" << detail::type_name<T>() << ", " << Radix << ", "
0807            << MinDigits << ", " << MaxDigits << ">";
0808         detail::print_expected(context, os, parser.expected_);
0809     }
0810 
0811     template<
0812         typename Context,
0813         typename T,
0814         int Radix,
0815         int MinDigits,
0816         int MaxDigits,
0817         typename Expected>
0818     void print_parser(
0819         Context const & context,
0820         int_parser<T, Radix, MinDigits, MaxDigits, Expected> const & parser,
0821         std::ostream & os,
0822         int components)
0823     {
0824         if (Radix == 10 && MinDigits == 1 && MaxDigits == -1) {
0825             if (std::is_same_v<T, short>) {
0826                 os << "short_";
0827                 detail::print_expected(context, os, parser.expected_);
0828                 return;
0829             } else if (std::is_same_v<T, int>) {
0830                 os << "int_";
0831                 detail::print_expected(context, os, parser.expected_);
0832                 return;
0833             } else if (std::is_same_v<T, long>) {
0834                 os << "long_";
0835                 detail::print_expected(context, os, parser.expected_);
0836                 return;
0837             } else if (std::is_same_v<T, long long>) {
0838                 os << "long_long";
0839                 detail::print_expected(context, os, parser.expected_);
0840                 return;
0841             }
0842         }
0843         os << "int<" << detail::type_name<T>() << ", " << Radix << ", "
0844            << MinDigits << ", " << MaxDigits << ">";
0845         detail::print_expected(context, os, parser.expected_);
0846     }
0847 
0848     template<typename Context>
0849     void print_parser(
0850         Context const & context,
0851         int_parser<short> const & parser,
0852         std::ostream & os,
0853         int components)
0854     {
0855         os << "short_";
0856     }
0857 
0858     template<typename Context>
0859     void print_parser(
0860         Context const & context,
0861         int_parser<long> const & parser,
0862         std::ostream & os,
0863         int components)
0864     {
0865         os << "long_";
0866     }
0867 
0868     template<typename Context>
0869     void print_parser(
0870         Context const & context,
0871         int_parser<long long> const & parser,
0872         std::ostream & os,
0873         int components)
0874     {
0875         os << "long_long";
0876     }
0877 
0878     template<typename Context, typename T>
0879     void print_parser(
0880         Context const & context,
0881         float_parser<T> const & parser,
0882         std::ostream & os,
0883         int components)
0884     {
0885         os << "float<" << detail::type_name<T>() << ">";
0886     }
0887 
0888     template<typename Context>
0889     void print_parser(
0890         Context const & context,
0891         float_parser<float> const & parser,
0892         std::ostream & os,
0893         int components)
0894     {
0895         os << "float_";
0896     }
0897 
0898     template<typename Context>
0899     void print_parser(
0900         Context const & context,
0901         float_parser<double> const & parser,
0902         std::ostream & os,
0903         int components)
0904     {
0905         os << "double_";
0906     }
0907 
0908     template<
0909         typename Context,
0910         typename ParserTuple,
0911         typename BacktrackingTuple,
0912         typename CombiningGroups>
0913     void print_switch_matchers(
0914         Context const & context,
0915         seq_parser<ParserTuple, BacktrackingTuple, CombiningGroups> const &
0916             parser,
0917         std::ostream & os,
0918         int components)
0919     {
0920         using namespace literals;
0921         os << "(";
0922         detail::print(
0923             os,
0924             detail::resolve(
0925                 context, parser::get(parser.parsers_, 0_c).pred_.value_));
0926         os << ", ";
0927         detail::print_parser(
0928             context, parser::get(parser.parsers_, 1_c), os, components);
0929         os << ")";
0930     }
0931 
0932     template<typename Context, typename ParserTuple>
0933     void print_switch_matchers(
0934         Context const & context,
0935         or_parser<ParserTuple> const & parser,
0936         std::ostream & os,
0937         int components)
0938     {
0939         using namespace literals;
0940 
0941         bool printed_ellipsis = false;
0942         hl::for_each(parser.parsers_, [&](auto const & parser) {
0943             if (components == parser_component_limit) {
0944                 if (!printed_ellipsis)
0945                     os << "...";
0946                 printed_ellipsis = true;
0947                 return;
0948             }
0949             detail::print_switch_matchers(context, parser, os, components);
0950             ++components;
0951         });
0952     }
0953 
0954     template<typename Context, typename SwitchValue, typename OrParser>
0955     void print_parser(
0956         Context const & context,
0957         switch_parser<SwitchValue, OrParser> const & parser,
0958         std::ostream & os,
0959         int components)
0960     {
0961         os << "switch_(";
0962         detail::print(os, detail::resolve(context, parser.switch_value_));
0963         os << ")";
0964         detail::print_switch_matchers(
0965             context, parser.or_parser_, os, components);
0966     }
0967 
0968 }}}
0969 
0970 #endif