@@ -5421,6 +5421,29 @@ namespace boost { namespace parser {
54215421
54225422#endif
54235423
5424+ namespace detail {
5425+ template <typename T>
5426+ using base_member_function_template_expr =
5427+ decltype (std::declval<T>().template base<2 >());
5428+ template <typename T>
5429+ constexpr bool has_base_member_function_template_v =
5430+ is_detected_v<base_member_function_template_expr, T>;
5431+
5432+ template <typename T>
5433+ using has_digits1_member_function_template_expr =
5434+ decltype (std::declval<T>().template digits<1 >());
5435+ template <typename T>
5436+ constexpr bool has_digits1_member_function_template_v =
5437+ is_detected_v<has_digits1_member_function_template_expr, T>;
5438+
5439+ template <typename T>
5440+ using has_digits2_member_function_template_expr =
5441+ decltype (std::declval<T>().template digits<1 , 2 >());
5442+ template <typename T>
5443+ constexpr bool has_digits2_member_function_template_v =
5444+ is_detected_v<has_digits2_member_function_template_expr, T>;
5445+ }
5446+
54245447 // Parser interface.
54255448
54265449 template <typename Parser, typename GlobalState, typename ErrorHandler>
@@ -5760,7 +5783,7 @@ namespace boost { namespace parser {
57605783 return parser_.call (first, last, context, skip, flags, success);
57615784 }
57625785
5763- /* * Applies `parser_`, assiging the parsed attribute, if any, to
5786+ /* * Applies `parser_`, assinging the parsed attribute, if any, to
57645787 `attr`, unless the attribute is reported via callback. */
57655788 template <
57665789 typename Iter,
@@ -5780,6 +5803,60 @@ namespace boost { namespace parser {
57805803 parser_.call (first, last, context, skip, flags, success, attr);
57815804 }
57825805
5806+ /* * Returns a new `parser_interface` constructed from
5807+ `parser_.base<Radix2>()`. Note that this only works for integral
5808+ numeric parsers like `int_` and `uint_`. */
5809+ template <int Radix2>
5810+ constexpr auto base () const noexcept
5811+ {
5812+ if constexpr (detail::has_base_member_function_template_v<
5813+ parser_type>) {
5814+ return parser::parser_interface{
5815+ parser_.template base <Radix2>()};
5816+ } else {
5817+ static_assert (
5818+ detail::has_base_member_function_template_v<parser_type>,
5819+ " Only certain parsers have a .base<>() member function. "
5820+ " This is not one of them." );
5821+ }
5822+ }
5823+
5824+ /* * Returns a new `parser_interface` constructed from
5825+ `parser_.digits<Digits>()`. Note that this only works for
5826+ integral numeric parsers like `int_` and `uint_`. */
5827+ template <int Digits>
5828+ constexpr auto digits () const noexcept
5829+ {
5830+ if constexpr (detail::has_digits1_member_function_template_v<
5831+ parser_type>) {
5832+ return parser::parser_interface{
5833+ parser_.template digits <Digits>()};
5834+ } else {
5835+ static_assert (
5836+ detail::has_digits1_member_function_template_v<parser_type>,
5837+ " Only certain parsers have a .base<>() member function. "
5838+ " This is not one of them." );
5839+ }
5840+ }
5841+
5842+ /* * Returns a new `parser_interface` constructed from
5843+ `parser_.digits<MinDigits2, MaxDigits2>()`. Note that this only
5844+ works for integral numeric parsers like `int_` and `uint_`. */
5845+ template <int MinDigits2, int MaxDigits2>
5846+ constexpr auto digits () const noexcept
5847+ {
5848+ if constexpr (detail::has_digits2_member_function_template_v<
5849+ parser_type>) {
5850+ return parser::parser_interface{
5851+ parser_.template digits <MinDigits2, MaxDigits2>()};
5852+ } else {
5853+ static_assert (
5854+ detail::has_digits2_member_function_template_v<parser_type>,
5855+ " Only certain parsers have a .base<>() member function. "
5856+ " This is not one of them." );
5857+ }
5858+ }
5859+
57835860 parser_type parser_;
57845861 global_state_type globals_;
57855862 error_handler_type error_handler_;
@@ -7926,7 +8003,11 @@ namespace boost { namespace parser {
79268003 typename Expected>
79278004 struct uint_parser
79288005 {
7929- static_assert (2 <= Radix && Radix <= 36 , " Unsupported radix." );
8006+ static_assert (
8007+ Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16 ,
8008+ " Unsupported radix." );
8009+ static_assert (1 <= MinDigits);
8010+ static_assert (MaxDigits == -1 || MinDigits <= MaxDigits);
79308011
79318012 constexpr uint_parser () {}
79328013 explicit constexpr uint_parser (Expected expected) : expected_(expected)
@@ -7992,6 +8073,33 @@ namespace boost { namespace parser {
79928073 return parser_interface{parser_t {expected}};
79938074 }
79948075
8076+ /* * Returns a `uint_parser` identical to `*this`, except that it
8077+ parses digits as base-`Radix2` instead of base-`Radix`. */
8078+ template <int Radix2>
8079+ constexpr auto base () const noexcept
8080+ {
8081+ return uint_parser<T, Radix2, MinDigits, MaxDigits, Expected>{
8082+ expected_};
8083+ }
8084+
8085+ /* * Returns a `uint_parser` identical to `*this`, except that it only
8086+ accepts numbers exactly `Digits` digits. */
8087+ template <int Digits>
8088+ constexpr auto digits () const noexcept
8089+ {
8090+ return uint_parser<T, Radix, Digits, Digits, Expected>{expected_};
8091+ }
8092+
8093+ /* * Returns a `uint_parser` identical to `*this`, except that it
8094+ only accepts numbers `D` digits long, where `D` is in
8095+ [`MinDigits2`, MaxDigits2`]. */
8096+ template <int MinDigits2, int MaxDigits2>
8097+ constexpr auto digits () const noexcept
8098+ {
8099+ return uint_parser<T, Radix, MinDigits2, MaxDigits2, Expected>{
8100+ expected_};
8101+ }
8102+
79958103 Expected expected_;
79968104 };
79978105
@@ -8039,6 +8147,8 @@ namespace boost { namespace parser {
80398147 static_assert (
80408148 Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16 ,
80418149 " Unsupported radix." );
8150+ static_assert (1 <= MinDigits);
8151+ static_assert (MaxDigits == -1 || MinDigits <= MaxDigits);
80428152
80438153 constexpr int_parser () {}
80448154 explicit constexpr int_parser (Expected expected) : expected_(expected)
@@ -8104,6 +8214,33 @@ namespace boost { namespace parser {
81048214 return parser_interface{parser_t {expected}};
81058215 }
81068216
8217+ /* * Returns an `int_parser` identical to `*this`, except that it
8218+ parses digits as base-`Radix2` instead of base-`Radix`. */
8219+ template <int Radix2>
8220+ constexpr auto base () const noexcept
8221+ {
8222+ return int_parser<T, Radix2, MinDigits, MaxDigits, Expected>{
8223+ expected_};
8224+ }
8225+
8226+ /* * Returns an `int_parser` identical to `*this`, except that it only
8227+ accepts numbers exactly `Digits` digits. */
8228+ template <int Digits>
8229+ constexpr auto digits () const noexcept
8230+ {
8231+ return int_parser<T, Radix, Digits, Digits, Expected>{expected_};
8232+ }
8233+
8234+ /* * Returns an `int_parser` identical to `*this`, except that it
8235+ only accepts numbers `D` digits long, where `D` is in
8236+ [`MinDigits2`, MaxDigits2`]. */
8237+ template <int MinDigits2, int MaxDigits2>
8238+ constexpr auto digits () const noexcept
8239+ {
8240+ return int_parser<T, Radix, MinDigits2, MaxDigits2, Expected>{
8241+ expected_};
8242+ }
8243+
81078244 Expected expected_;
81088245 };
81098246
0 commit comments