1

Reading the documentation, I think the below should work correctly, but instead it fails to compile unless I don't pass output to the phrase_parse call, in which case it works correctly, though I can't get the data I want. It seems that nvp_def has types of (string, unused_type, uin32_t) which (as I read the documentation) would create a tuple as I'm expecting, but this obviously isn't the case. What am I missing to be able to get the parse data?

#include <boost/spirit/home/x3.hpp>
#include <tuple>
namespace x3 = boost::spirit::x3;

x3::rule<class idtype, std::string> const idrule = "idrule";
auto const idrule_def = x3::lexeme[+x3::char_("a-zA-Z0-9")];

x3::rule<class nvp, std::tuple<std::string, uint32_t>> const nvp = "nvp";
auto const nvp_def = idrule >> x3::char_(':') >> x3::hex;

BOOST_SPIRIT_DEFINE(idrule, nvp);

int main(int argc, char *argv[])
{
    std::tuple<std::string, uint32_t> output;

    const std::string total =  "foo4bar:deadbeef";
    std::string::const_iterator first = total.begin();
    std::string::const_iterator const last = total.end();

    bool r = x3::phrase_parse(first, last, nvp, x3::space, output);
}

Compile error (trying to assign a uint32_t from hex to a tuple):

/usr/include/boost/spirit/home/x3/support/traits/move_to.hpp:62: error: no match for ‘operator=’ (operand types are ‘std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned int>’ and ‘std::remove_reference<unsigned int&>::type {aka unsigned int}’)
         dest = std::move(src);
         ~~~~~^~~~~~~~~~~~~~~~
byteit101
  • 3,910
  • 2
  • 20
  • 29

1 Answers1

2

Your main issue is a missing include: <boost/fusion/include/std_tuple.hpp>; without this adapter std::tuple is not a valid Fusion sequence, so Spirit is consequently unable to use it to store compound attributes. (N.b. your example is also missing <string> and <stdint.h>.)

Your second issue is that x3::char_ has an attribute, but you don't want an attribute for the delimiting colon, so nvp_def should be idrule >> ':' >> x3::hex or idrule >> x3::lit(':') >> x3::hex. Note also that the actual attribute of x3::hex is unsigned, so using a uint32_t field to store it may truncate on some platforms.

ildjarn
  • 62,044
  • 9
  • 127
  • 211
  • 1
    With various simplifications http://coliru.stacked-crooked.com/a/cb4962d72929119d – sehe Jul 07 '18 at 22:14