45018

What is the correct way to use boost::qi::rule with BOOST_FUSION_ADAPT_STRUCT?

I am attempting to get a qi::rule<> to emit a struct with BOOST_FUSION_ADAPT_STRUCT based on the boost employee example.

I have the following struct and its associated fusion macro:

struct LineOnCommand { int lineNum; std::vector<char> humpType; }; BOOST_FUSION_ADAPT_STRUCT( LineOnCommand, (int, lineNum) (std::vector<char>, humpType) )

The associated parsing rules are:

qi::rule<Iterator, std::vector<char> ascii::space_type> humpIdentifer = qi::lit("BH") | qi::lit("DH"); qi::rule<Iterator, LineOnCommand(), ascii::space_type> Cmd_LNON = qi::int_ >> -humpIdentifier >> qi::lit("LNON");

I then have a compound rule, of which all others (including this simple test case) are a part which is passed to the parser:

qi::rule<Iterator, qi::unused_type, ascii::space_type> commands = +( /* other rules | */ Cmd_LNON /*| other rules */); bool success = qi::phrase_parse(StartIterator, EndIterator, commands, ascii::space);

The problem comes when I attempt to compile, and I get the error:

<boostsource>/spirit/home/qi/detail/assign_to.hpp(152): error: no suitable constructor exists to convert form "const int" to "LineOnCommand" attr = static_cast<Attribute>(val);

Clearly I'm doing something wrong, but I'm not sure what. If I understand the way spirit works, the 2nd argument to the template of the rule represents the attribute (i.e. the data type emitted by the rule), and the BOOST_FUSION_ADAPT_STRUCT macro will adapt my struct so that boost knows how to convert a stream that is "int, std::vector" to it.

The only difference between what I'm doing here and the boost employee example is that I'm not using an explicit grammar to do the parsing. My understanding is this is not necessary, and that a rule by itself is sufficient.

What am I doing wrong?

Answer1:

I'm not sure. I think I'm missing the problem. Perhaps, I "naturally" sidestep the problem because your sample is not self-contained.

So, here's my take on it: <strong>See it Live On Coliru</strong>, in the hope that just comparing things helps you:

    <li>I fixed the obvious typos in your rule declaration</li> <li>

    I suggested something other than qi::unused_type; if there's no attribute, there's no need to state it; beyond the iterator type, the template arguments to qi::rule and qi::grammar are not positional. So

    qi::rule<It, qi::unused_type(), ascii::space_type> r; qi::rule<It, ascii::space_type, qi::unused_type()> r; qi::rule<It, ascii::space_type> r;

    are all /logically/ equivalent.

    </li> </ul>

    Full listing:

    #include <boost/fusion/adapted/struct.hpp> #include <boost/spirit/include/qi.hpp> namespace qi = boost::spirit::qi; namespace ascii = boost::spirit::ascii; struct LineOnCommand { int lineNum; std::vector<char> humpType; }; BOOST_FUSION_ADAPT_STRUCT( LineOnCommand, (int, lineNum) (std::vector<char>, humpType) ) template <typename It, typename Skipper = ascii::space_type> struct parser : qi::grammar<It, std::vector<LineOnCommand>(), Skipper> { parser() : parser::base_type(commands) { using namespace qi; humpIdentifier = string("BH") | string("DH"); Cmd_LNON = int_ >> -humpIdentifier >> "LNON"; commands = +( /* other rules | */ Cmd_LNON /*| other rules */ ); } private: qi::rule<It, std::vector<char>(), Skipper> humpIdentifier; qi::rule<It, LineOnCommand(), Skipper> Cmd_LNON; qi::rule<It, std::vector<LineOnCommand>(), Skipper> commands; }; int main() { typedef std::string::const_iterator Iterator; parser<Iterator> p; std::string const input = "123 BH LNON\n" "124 LNON\t\t\t" "125 DH LNON\n" "126 INVALID LNON"; auto f(input.begin()), l(input.end()); std::vector<LineOnCommand> data; bool success = qi::phrase_parse(f, l, p, ascii::space, data); std::cout << "success:" << std::boolalpha << success << ", " << "elements: " << data.size() << "\n"; if (success) { for (auto& el : data) { std::cout << "Item: " << el.lineNum << ", humpType '" << std::string(el.humpType.begin(), el.humpType.end()) << "'\n"; } } if (f!=l) std::cout << "Trailing unparsed: '" << std::string(f,l) << "'\n"; return success? 0 : 1; }

    Output:

    success:true, elements: 3 Item: 123, humpType 'BH' Item: 124, humpType '' Item: 125, humpType 'DH' Trailing unparsed: '126 INVALID LNON'

Recommend

  • Spirit X3, semantic action makes compilation fails with: Attribute does not have the expected size
  • Spirit parser segfaults
  • Parse tab delimited file with Boost.Spirit where entries may contain whitespace in
  • Memory dump much smaller than available memory
  • Dom Node for PHP find href attribute issue
  • Can I put a + sign in a folder with IIS?
  • G1 Collector not doing full GC
  • KornShell Printf - Padding a string
  • finding greatest prime factor using recursion in c
  • substitute period from abbreviation (single letter + period) unless followed by a capital letter
  • Pass nested C++ vector as built-in style multi-dimensional array
  • numpy 64bit support in PTVS and numpy System.Int64 casting
  • ASP.NET MVC2 Error: No parameterless constructor defined for this object
  • How can I print out a large table of symbols from MATLAB to form a cross-stitch chart?
  • Generate a unique string based on a pair of strings
  • PHPStorm Namespace support not working for Symfony2 projects
  • Deleting a widget from QTableView
  • Embedded Google Maps in Rails not responsive
  • Efficient User-Agent Regex to find Safari in Python
  • multidatatrigger with multibinding in ControlTemplate.Triggers
  • Cross platform UI spacing/padding
  • Is there a parser equivalent of 'fragment' marking in ANTLR4?
  • Build Successful but not running on simulator
  • Django model inheritance, filtering models
  • IE11 throwing “SCRIPT1014: invalid character” where all other browsers work
  • nonblocking BIO_do_connect blocked when there is no internet connected
  • Typescript - Unable to get 'import' statement to function
  • Get data from AJAX - How to
  • Splitting given String into two variables - php
  • Bug in WPF DataGrid
  • Running a C# exe file
  • Join two tables and save into third-sql
  • How to model a transition system with SPIN
  • ORA-29908: missing primary invocation for ancillary operator
  • 0x202A in filename: Why?
  • Run Powershell script from inside other Powershell script with dynamic redirection to file
  • Memory offsets in inline assembly
  • How does Linux kernel interrupt the application?
  • Running Map reduces the dimensions of the matrices
  • Converting MP3 duration time