diff --git a/doc/parser.qbk b/doc/parser.qbk index 88d1f15e..6e7db11a 100644 --- a/doc/parser.qbk +++ b/doc/parser.qbk @@ -105,6 +105,9 @@ [def _cbp_ [funcref boost::parser::callback_parse `callback_parse()`]] [def _cbpp_ [funcref boost::parser::callback_prefix_parse `callback_prefix_parse()`]] +[def _attr_ [classref boost::parser::attribute `attribute`]] +[def _attr_t_ [classref boost::parser::attribute_t `attribute_t`]] + [def _w_glb_ [funcref boost::parser::with_globals `with_globals()`]] [def _w_eh_ [funcref boost::parser::with_error_handler `with_error_handler()`]] diff --git a/doc/tutorial.qbk b/doc/tutorial.qbk index 9bbca3e9..1a19d2c6 100644 --- a/doc/tutorial.qbk +++ b/doc/tutorial.qbk @@ -66,10 +66,9 @@ subparsers does. _Parser_ parsers each have an /attribute/ associated with them, or explicitly have no attribute. An attribute is a value that the parser generates when it matches the input. For instance, the parser _d_ generates a `double` when it -matches the input. Since it is not possible to write a type trait that -returns the attribute type of a parser, we need notation for concisely -communicating that relationship. _ATTR_ is a notional macro that expands to -the attribute type of the parser passed to it; `_ATTR_np_(_d_)` is `double`. +matches the input. _ATTR_ is a notional macro that expands to the attribute +type of the parser passed to it; `_ATTR_np_(_d_)` is `double`. This is +similar to the _attr_ type trait. Next, we'll look at some simple programs that parse using _Parser_. We'll start small and build up from there. @@ -151,6 +150,10 @@ In fact, the return type of this call to _p_ is `std::nullopt` is returned. We'll look at how _Parser_ maps the type of the parser to the return type, or the filled in out-parameter's type, a bit later. +[note There's a type trait that can tell you the attribute type for a parser, +_attr_ (and an associated alias _attr_t_). We'll discuss it more in the +_attr_gen_ section.] + If I run it in a shell, this is the result: [pre @@ -1326,6 +1329,30 @@ parse.] moved, copy, and default constructed. There is no support for move-only or non-default-constructible types.] +[heading The attribute type trait, _attr_] + +You can use _attr_ (and the associated alias, _attr_t_) to determine the +attribute a parser would have if it were passed to _p_. Since at least one +parser (_ch_) has a polymorphic attribute type, _attr_ also takes the type of +the range being parsed. If a parser produces no attribute, _attr_ will +produce _n_, not `void`. + +If you want to feed an iterator/sentinel pair to _attr_, create a range from +it like so: + + constexpr auto parser = /* ... */; + auto first = /* ... */; + auto const last = /* ... */; + + namespace bp = boost::parser; + // You can of course use std::ranges::subrange directly in C++20 and later. + using attr_type = bp::attribute_t; + +There is no single attribute type for any parser, since a parser can be placed +within _omit_, which makes its attribute type _n_. Therefore, _attr_ cannot +tell you what attribute your parser will produce under all circumstances; it +only tells you what it would produce if it were passed to _p_. + [heading Parser attributes] [table_attribute_generation] diff --git a/include/boost/parser/parser.hpp b/include/boost/parser/parser.hpp index 43cd9308..e0c73c23 100644 --- a/include/boost/parser/parser.hpp +++ b/include/boost/parser/parser.hpp @@ -373,6 +373,8 @@ namespace boost { namespace parser { template using print_type = typename print_t::type; + template + struct attribute_impl; // Utility types. @@ -1459,6 +1461,7 @@ namespace boost { namespace parser { } inline bool make_parse_result(nope &, bool success) { return success; } + inline bool make_parse_result(none &, bool success) { return success; } template struct char_pair @@ -2039,27 +2042,7 @@ namespace boost { namespace parser { // API implementations template - auto has_attribute(Iter first, Sentinel last, Parser parser) - { - constexpr auto flags = detail::flags::gen_attrs; - using context = decltype(detail::make_context( - first, - last, - std::declval(), - std::declval(), - parser.error_handler_, - parser.globals_, - std::declval())); - using attr_t = decltype(parser( - std::false_type{}, - first, - last, - std::declval(), - detail::null_parser{}, - flags, - std::declval())); - return std::integral_constant>{}; - } + auto has_attribute(Iter first, Sentinel last, Parser parser); template struct scoped_base_assign @@ -2151,14 +2134,9 @@ namespace boost { namespace parser { auto const flags = Debug ? detail::enable_trace(detail::flags::gen_attrs) : detail::flags::gen_attrs; - using attr_t = decltype(parser( - std::false_type{}, - first, - last, - context, - detail::null_parser{}, - flags, - success)); + using attr_t = typename detail::attribute_impl< + BOOST_PARSER_SUBRANGE, Sentinel>, + Parser>::type; try { attr_t attr_ = parser( std::false_type{}, @@ -2317,8 +2295,9 @@ namespace boost { namespace parser { Debug ? detail::enable_trace(detail::default_flags()) : detail::default_flags(); detail::skip(first, last, skip, flags); - using attr_t = decltype(parser( - std::false_type{}, first, last, context, skip, flags, success)); + using attr_t = typename detail::attribute_impl< + BOOST_PARSER_SUBRANGE, Sentinel>, + Parser>::type; try { attr_t attr_ = parser( std::false_type{}, @@ -5969,7 +5948,7 @@ namespace boost { namespace parser { constexpr char_parser(Expected expected) : expected_(expected) {} template - using attribute_t = std::conditional_t< + using attribute_type = std::conditional_t< std::is_same_v, std::decay_t, AttributeType>; @@ -5987,9 +5966,9 @@ namespace boost { namespace parser { Context const & context, SkipParser const & skip, detail::flags flags, - bool & success) const -> attribute_t + bool & success) const -> attribute_type { - attribute_t retval; + attribute_type retval; call(use_cbs, first, last, context, skip, flags, success, retval); return retval; } @@ -6018,7 +5997,7 @@ namespace boost { namespace parser { success = false; return; } - attribute_t const x = *first; + attribute_type const x = *first; if (detail::unequal(context, x, expected_)) { success = false; return; @@ -6140,7 +6119,7 @@ namespace boost { namespace parser { constexpr digit_parser() {} template - using attribute_t = std::decay_t; + using attribute_type = std::decay_t; template< bool UseCallbacks, @@ -6155,9 +6134,9 @@ namespace boost { namespace parser { Context const & context, SkipParser const & skip, detail::flags flags, - bool & success) const -> attribute_t + bool & success) const -> attribute_type { - attribute_t retval; + attribute_type retval; call(use_cbs, first, last, context, skip, flags, success, retval); return retval; } @@ -6186,7 +6165,7 @@ namespace boost { namespace parser { success = false; return; } - attribute_t const x = *first; + attribute_type const x = *first; char32_t const x_cmp = x; if (x_cmp < U'\x0100' && (x_cmp < U'0' || U'9' < x_cmp)) { success = false; @@ -6292,7 +6271,7 @@ namespace boost { namespace parser { } template - using attribute_t = std::decay_t; + using attribute_type = std::decay_t; template< bool UseCallbacks, @@ -6307,9 +6286,9 @@ namespace boost { namespace parser { Context const & context, SkipParser const & skip, detail::flags flags, - bool & success) const -> attribute_t + bool & success) const -> attribute_type { - attribute_t retval; + attribute_type retval; call(use_cbs, first, last, context, skip, flags, success, retval); return retval; } @@ -6340,7 +6319,7 @@ namespace boost { namespace parser { } auto const & chars = detail::char_set::chars; - attribute_t const x = *first; + attribute_type const x = *first; uint32_t const x_cmp = x; if (x_cmp < U'\x0100') { uint32_t const * it = std::lower_bound( @@ -6376,7 +6355,7 @@ namespace boost { namespace parser { constexpr char_subrange_parser() {} template - using attribute_t = std::decay_t; + using attribute_type = std::decay_t; template< bool UseCallbacks, @@ -6391,9 +6370,9 @@ namespace boost { namespace parser { Context const & context, SkipParser const & skip, detail::flags flags, - bool & success) const -> attribute_t + bool & success) const -> attribute_type { - attribute_t retval; + attribute_type retval; call(use_cbs, first, last, context, skip, flags, success, retval); return retval; } @@ -6422,7 +6401,7 @@ namespace boost { namespace parser { success = false; return; } - attribute_t const x = *first; + attribute_type const x = *first; char32_t const x_cmp = x; success = false; for (auto subrange : detail::char_subranges::ranges) { @@ -8386,6 +8365,61 @@ namespace boost { namespace parser { } } + namespace detail { + template + struct attribute_impl + { + using parser_type = typename Parser::parser_type; + using global_state_type = typename Parser::global_state_type; + using error_handler_type = typename Parser::error_handler_type; + + using iterator = detail::iterator_t; + using sentinel = detail::sentinel_t; + + using context = decltype(detail::make_context( + std::declval(), + std::declval(), + std::declval(), + std::declval(), + std::declval(), + std::declval(), + std::declval())); + using type = decltype(std::declval()( + std::false_type{}, + std::declval(), + std::declval(), + std::declval(), + detail::null_parser{}, + detail::flags::gen_attrs, + std::declval())); + }; + + template + auto has_attribute(Iter first, Sentinel last, Parser parser) + { + using attr_t = typename attribute_impl< + BOOST_PARSER_SUBRANGE, + Parser>::type; + return std::integral_constant>{}; + } + + template + constexpr wrapper attr_wrapped_final; + template<> + inline constexpr wrapper attr_wrapped_final; + } + + template + struct attribute + { + using initial_type = typename detail::attribute_impl< + decltype(detail::make_input_subrange(std::declval())), + Parser>::type; + using type = + typename decltype(detail::attr_wrapped_final)::type; + }; + + namespace detail { template constexpr void static_assert_merge_attributes(tuple parsers) diff --git a/include/boost/parser/parser_fwd.hpp b/include/boost/parser/parser_fwd.hpp index dbe4fdb3..86d27262 100644 --- a/include/boost/parser/parser_fwd.hpp +++ b/include/boost/parser/parser_fwd.hpp @@ -43,6 +43,20 @@ namespace boost { namespace parser { constexpr bool enable_variant> = true; #endif + /** A type trait that evaluates to the attribute type for parser `Parser` + used to parse range `R`, as if by calling `parse(r, parser)`, using + some `R r` and `Parser parser`. Note that this implies that pointers + to null-terminated strings are supported types for `R`. The result is + not wrapped in a `std::optional` like the result of a call to + `parse()` would be. If `Parser` produces no attribute, the result is + the no-attribute sentinel type `none`. */ + template + struct attribute; + + /** An alias for `typename attribute::type`. */ + template + using attribute_t = typename attribute::type; + namespace detail { template constexpr bool is_optional_v = enable_optional; diff --git a/test/compile_attribute.cpp b/test/compile_attribute.cpp index cc26312f..e0c980c2 100644 --- a/test/compile_attribute.cpp +++ b/test/compile_attribute.cpp @@ -18,26 +18,41 @@ void compile_attribute_non_unicode() constexpr auto parser = char_; using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + char>); } { constexpr auto parser = *char_; using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } { constexpr auto parser = string("foo"); using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } { constexpr auto parser = char_ >> string("foo"); using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } { constexpr auto parser = string("foo") >> char_; using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } } // pointer-as-range (covers iter/sent case, as that's what gets used @@ -49,26 +64,41 @@ void compile_attribute_non_unicode() constexpr auto parser = char_; using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + char>); } { constexpr auto parser = *char_; using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } { constexpr auto parser = string("foo"); using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } { constexpr auto parser = char_ >> string("foo"); using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } { constexpr auto parser = string("foo") >> char_; using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } } // iter/iter @@ -81,26 +111,51 @@ void compile_attribute_non_unicode() constexpr auto parser = char_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + char>); } { constexpr auto parser = *char_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { constexpr auto parser = string("foo"); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { constexpr auto parser = char_ >> string("foo"); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { constexpr auto parser = string("foo") >> char_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } } } @@ -117,26 +172,51 @@ void compile_attribute_unicode_utf8() constexpr auto parser = char_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + char32_t>); } { constexpr auto parser = *char_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { constexpr auto parser = string("foo"); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { constexpr auto parser = char_ >> string("foo"); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { constexpr auto parser = string("foo") >> char_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } } #endif @@ -148,26 +228,41 @@ void compile_attribute_unicode_utf8() constexpr auto parser = char_; using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + char32_t>); } { constexpr auto parser = *char_; using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } { constexpr auto parser = string("foo"); using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } { constexpr auto parser = char_ >> string("foo"); using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } { constexpr auto parser = string("foo") >> char_; using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } } #if defined(__cpp_char8_t) @@ -178,26 +273,41 @@ void compile_attribute_unicode_utf8() constexpr auto parser = char_; using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + char32_t>); } { constexpr auto parser = *char_; using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } { constexpr auto parser = string("foo"); using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } { constexpr auto parser = char_ >> string("foo"); using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } { constexpr auto parser = string("foo") >> char_; using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } } { @@ -207,26 +317,41 @@ void compile_attribute_unicode_utf8() constexpr auto parser = char_; using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + char32_t>); } { constexpr auto parser = *char_; using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } { constexpr auto parser = string("foo"); using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } { constexpr auto parser = char_ >> string("foo"); using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } { constexpr auto parser = string("foo") >> char_; using attr_t = decltype(parse(r, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } } #endif @@ -243,26 +368,51 @@ void compile_attribute_unicode_utf32() constexpr auto parser = char_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + char32_t>); } { constexpr auto parser = *char_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { constexpr auto parser = string("foo"); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { constexpr auto parser = char_ >> string("foo"); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { constexpr auto parser = string("foo") >> char_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } } { @@ -270,26 +420,41 @@ void compile_attribute_unicode_utf32() constexpr auto parser = char_; using attr_t = decltype(parse(U"", parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + char32_t>); } { constexpr auto parser = *char_; using attr_t = decltype(parse(U"", parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } { constexpr auto parser = string("foo"); using attr_t = decltype(parse(U"", parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } { constexpr auto parser = char_ >> string("foo"); using attr_t = decltype(parse(U"", parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } { constexpr auto parser = string("foo") >> char_; using attr_t = decltype(parse(U"", parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t, + std::string>); } } } @@ -315,211 +480,406 @@ void compile_attribute_sentinel() constexpr auto parser = eps; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { constexpr auto parser = eol; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { constexpr auto parser = eoi; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { constexpr auto parser = attr(3.0); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + double>); } { constexpr auto parser = attr('c'); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + char>); } { constexpr auto parser = cp; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + char32_t>); } { constexpr auto parser = cu; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + char>); } { using namespace boost::parser::literals; constexpr auto parser = 'c'_l; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { using namespace boost::parser::literals; constexpr auto parser = u8'c'_l; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { using namespace boost::parser::literals; constexpr auto parser = U'c'_l; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { using namespace boost::parser::literals; constexpr auto parser = "str"_l; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { using namespace boost::parser::literals; constexpr auto parser = u8"str"_l; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { using namespace boost::parser::literals; constexpr auto parser = U"str"_l; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { using namespace boost::parser::literals; constexpr auto parser = 'c'_p; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + char>); } { using namespace boost::parser::literals; constexpr auto parser = u8'c'_p; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + char>); } { using namespace boost::parser::literals; constexpr auto parser = U'c'_p; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + char>); } { using namespace boost::parser::literals; constexpr auto parser = "str"_p; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { using namespace boost::parser::literals; constexpr auto parser = u8"str"_p; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { using namespace boost::parser::literals; constexpr auto parser = U"str"_p; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { constexpr auto parser = lit('c'); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { constexpr auto parser = lit(U'c'); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { constexpr auto parser = lit("str"); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { std::string str = "str"; auto parser = lit(str); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { constexpr auto parser = bool_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + bool>); } { constexpr auto parser = bin; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + unsigned int>); } { constexpr auto parser = oct; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + unsigned int>); } { constexpr auto parser = hex; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + unsigned int>); } { constexpr auto parser = ushort_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + unsigned short>); } { constexpr auto parser = uint_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + unsigned int>); } { constexpr auto parser = ulong_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + unsigned long>); } { constexpr auto parser = ulong_long; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert( std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + unsigned long long>); } { constexpr auto parser = short_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + short>); } { constexpr auto parser = int_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + int>); } { constexpr auto parser = long_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + long>); } { constexpr auto parser = long_long; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + long long>); } { constexpr auto parser = float_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + float>); } { constexpr auto parser = double_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + double>); } { symbols parser; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + float>); } { auto const c = [](auto & ctx) { return true; }; constexpr auto parser = if_(c)[double_]; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + double>); } { auto const x = [](auto & ctx) { return 2; }; @@ -527,18 +887,33 @@ void compile_attribute_sentinel() using attr_t = decltype(prefix_parse(first, last, parser)); static_assert( std::is_same_v>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::variant>); } { constexpr auto parser = int_ | int_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + int>); } { constexpr auto parser = double_ | int_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert( std::is_same_v>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::variant>); } { constexpr auto parser = double_ | int_ | eps; @@ -546,6 +921,11 @@ void compile_attribute_sentinel() static_assert(std::is_same_v< attr_t, std::optional>>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::optional>>); } { @@ -554,11 +934,21 @@ void compile_attribute_sentinel() static_assert(std::is_same_v< attr_t, std::optional>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + tuple>); } { constexpr auto parser = cu >> string("str"); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { @@ -566,6 +956,11 @@ void compile_attribute_sentinel() constexpr auto parser = cu[a]; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { @@ -580,6 +975,11 @@ void compile_attribute_sentinel() { using attr_t = decltype(prefix_parse(first, last, ints)); static_assert(std::is_same_v>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(ints)>, + std::vector>); } } @@ -598,211 +998,406 @@ void compile_attribute() constexpr auto parser = eps; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { constexpr auto parser = eol; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { constexpr auto parser = eoi; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { constexpr auto parser = attr(3.0); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + double>); } { constexpr auto parser = attr('c'); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + char>); } { constexpr auto parser = cp; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + char32_t>); } { constexpr auto parser = cu; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + char>); } { using namespace boost::parser::literals; constexpr auto parser = 'c'_l; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { using namespace boost::parser::literals; constexpr auto parser = u8'c'_l; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { using namespace boost::parser::literals; constexpr auto parser = U'c'_l; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { using namespace boost::parser::literals; constexpr auto parser = "str"_l; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { using namespace boost::parser::literals; constexpr auto parser = u8"str"_l; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { using namespace boost::parser::literals; constexpr auto parser = U"str"_l; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { using namespace boost::parser::literals; constexpr auto parser = 'c'_p; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + char>); } { using namespace boost::parser::literals; constexpr auto parser = u8'c'_p; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + char>); } { using namespace boost::parser::literals; constexpr auto parser = U'c'_p; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + char>); } { using namespace boost::parser::literals; constexpr auto parser = "str"_p; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { using namespace boost::parser::literals; constexpr auto parser = u8"str"_p; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { using namespace boost::parser::literals; constexpr auto parser = U"str"_p; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { constexpr auto parser = lit('c'); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { constexpr auto parser = lit(U'c'); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { constexpr auto parser = lit("str"); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { std::string str = "str"; auto parser = lit(str); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { constexpr auto parser = bool_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + bool>); } { constexpr auto parser = bin; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + unsigned int>); } { constexpr auto parser = oct; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + unsigned int>); } { constexpr auto parser = hex; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + unsigned int>); } { constexpr auto parser = ushort_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + unsigned short>); } { constexpr auto parser = uint_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + unsigned int>); } { constexpr auto parser = ulong_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + unsigned long>); } { constexpr auto parser = ulong_long; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert( std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + unsigned long long>); } { constexpr auto parser = short_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + short>); } { constexpr auto parser = int_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + int>); } { constexpr auto parser = long_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + long>); } { constexpr auto parser = long_long; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + long long>); } { constexpr auto parser = float_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + float>); } { constexpr auto parser = double_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + double>); } { symbols parser; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + float>); } { auto const c = [](auto & ctx) { return true; }; constexpr auto parser = if_(c)[double_]; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + double>); } { auto const x = [](auto & ctx) { return 2; }; @@ -810,18 +1405,33 @@ void compile_attribute() using attr_t = decltype(prefix_parse(first, last, parser)); static_assert( std::is_same_v>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::variant>); } { constexpr auto parser = int_ | int_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + int>); } { constexpr auto parser = double_ | int_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert( std::is_same_v>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::variant>); } { constexpr auto parser = double_ | int_ | eps; @@ -829,6 +1439,11 @@ void compile_attribute() static_assert(std::is_same_v< attr_t, std::optional>>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::optional>>); } { @@ -837,11 +1452,21 @@ void compile_attribute() static_assert(std::is_same_v< attr_t, std::optional>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + tuple>); } { constexpr auto parser = cu >> string("str"); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { @@ -849,6 +1474,11 @@ void compile_attribute() constexpr auto parser = cu[a]; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + none>); } { @@ -863,6 +1493,11 @@ void compile_attribute() { using attr_t = decltype(prefix_parse(first, last, ints)); static_assert(std::is_same_v>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(ints)>, + std::vector>); } { @@ -871,24 +1506,44 @@ void compile_attribute() static_assert(std::is_same_v< attr_t, std::optional>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + tuple>); } { constexpr auto parser = char_ >> string("str"); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { constexpr auto parser = char_ >> ' ' >> string("str"); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { constexpr auto parser = char_ >> ' ' >> string("str") >> ' ' >> char_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { @@ -896,5 +1551,10 @@ void compile_attribute() eps >> char_ >> ' ' >> string("str") >> ' ' >> char_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } } diff --git a/test/compile_or_attribute.cpp b/test/compile_or_attribute.cpp index 4f9a38a5..c7ec670e 100644 --- a/test/compile_or_attribute.cpp +++ b/test/compile_or_attribute.cpp @@ -20,6 +20,11 @@ void compile_or_attribute() using attr_t = decltype(prefix_parse(first, last, parser)); static_assert( std::is_same_v>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::optional>); } // scalar | scalar @@ -27,18 +32,33 @@ void compile_or_attribute() constexpr auto parser = char_ | char_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + char>); } { constexpr auto parser = char_ | char_ | eps; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert( std::is_same_v>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::optional>); } { constexpr auto parser = int_ | char_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert( std::is_same_v>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::variant>); } { constexpr auto parser = int_ | char_ | eps; @@ -46,6 +66,11 @@ void compile_or_attribute() static_assert(std::is_same_v< attr_t, std::optional>>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::optional>>); } // -scalar | -scalar @@ -54,12 +79,22 @@ void compile_or_attribute() using attr_t = decltype(prefix_parse(first, last, parser)); static_assert( std::is_same_v>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::optional>); } { constexpr auto parser = -char_ | -char_ | eps; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert( std::is_same_v>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::optional>); } { constexpr auto parser = -int_ | -char_; @@ -69,6 +104,11 @@ void compile_or_attribute() attr_t, std::optional< std::variant, std::optional>>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::variant, std::optional>>); } { constexpr auto parser = -int_ | -char_ | eps; @@ -78,6 +118,13 @@ void compile_or_attribute() attr_t, std::optional, std::optional>>>>); + static_assert( + std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::optional< + std::variant, std::optional>>>); } // seq | seq @@ -85,18 +132,33 @@ void compile_or_attribute() constexpr auto parser = *char_ | *char_; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert(std::is_same_v>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::string>); } { constexpr auto parser = *char_ | *char_ | eps; using attr_t = decltype(prefix_parse(first, last, parser)); static_assert( std::is_same_v>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::optional>); } { constexpr auto parser = *string("str") | *string("str"); using attr_t = decltype(prefix_parse(first, last, parser)); static_assert( std::is_same_v>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::vector>); } { constexpr auto parser = *string("str") | *string("str") | eps; @@ -104,6 +166,11 @@ void compile_or_attribute() static_assert(std::is_same_v< attr_t, std::optional>>>); + static_assert(std::is_same_v< + attribute_t< + decltype(BOOST_PARSER_SUBRANGE(first, last)), + decltype(parser)>, + std::optional>>); } // seq | seq