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
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