1
votes

I am trying to create a Spirit Karma grammar that is composed of several rules. This grammar is intended to create a string of the format "(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11)". The rule to print out each individual struct that I call RowData uses BOOST_FUSION_ADAPT_STRUCT to print out all of the fields of that struct. If the grammar only includes that rule, the grammar works fine. However, I am using this struct as the value of a std::map. The key in an integer but I do not care about that value and want to drop it. I have created rules to parse the std::map but the rule that handles the std::pair fails to compile for a BOOST_SPIRIT_ASSERT_MATCH. I have created a small bit of code that generates this issue. The line is pairRule = bs::karma::omit << rowDataRule; If anybody has an idea what the issue is or how I could do this differently, I would appreciate the help.

Edit: I am using gcc 4.8.3 on OpenSUSE 13.2 but get the same error with gcc 4.8.2 on Ubuntu 14.04 LTS.

main.cpp

#include <iostream>
#include <map>

#include <boost/cstdint.hpp>
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/make_tuple.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <boost/spirit/include/karma.hpp>

namespace bs = boost::spirit;

struct RowData
{
    RowData() :
        field0(0),
        field1(0),
        field2(0),
        field3(0)
    {
    }

    boost::uint64_t field0;
    boost::uint64_t field1;
    boost::uint64_t field2;
    boost::uint64_t field3;
};

BOOST_FUSION_ADAPT_STRUCT(
    RowData,
    (boost::uint64_t, field0)
    (boost::uint64_t, field1)
    (boost::uint64_t, field2)
    (boost::uint64_t, field3)
)

template <typename OutputIterator>
struct RowDataGrammar :
    bs::karma::grammar< OutputIterator, std::map<boost::uint64_t, RowData>() >
{
    RowDataGrammar() : RowDataGrammar::base_type(allRowsRule)
    {
        rowDataRule =
            bs::karma::lit("(") <<
            bs::karma::ulong_ <<
            bs::karma::lit(", ") <<
            bs::karma::ulong_ <<
            bs::karma::lit(", ") <<
            bs::karma::ulong_ <<
            bs::karma::lit(", ") <<
            bs::karma::ulong_ <<
            bs::karma::lit(")");

        // I only want the value from the map. The key is dropped.
        pairRule = bs::karma::omit << rowDataRule;

        allRowsRule = pairRule % ", ";
    }

private:
    bs::karma::rule< OutputIterator, RowData() > rowDataRule;
    bs::karma::rule< OutputIterator, std::pair<boost::uint64_t, RowData>() > pairRule;
    bs::karma::rule< OutputIterator, std::map<boost::uint64_t, RowData>() >  allRowsRule;
};

int main(int argc, char** argv)
{
    std::map<boost::uint64_t, RowData> rowMap;

    RowData rowData;
    rowData.field0 = 0;
    rowData.field1 = 1;
    rowData.field2 = 2;
    rowData.field3 = 3;
    rowMap.insert(std::make_pair(10, rowData));

    rowData.field0 = 6;
    rowData.field1 = 7;
    rowData.field2 = 8;
    rowData.field3 = 9;
    rowMap.insert(std::make_pair(20, rowData));

    std::string generatedString;
    std::back_insert_iterator<std::string> sink(generatedString);
    RowDataGrammar< std::back_insert_iterator<std::string> > grammar;

    bs::karma::generate(sink, grammar, rowMap);

    std::cout << "output :" << generatedString << std::endl;
}

Error message:

In file included from /usr/include/boost/fusion/support/tag_of.hpp:16:0,
                 from /usr/include/boost/fusion/support/category_of.hpp:11,
                 from /usr/include/boost/fusion/adapted/struct/detail/extension.hpp:13,
                 from /usr/include/boost/fusion/adapted/struct/adapt_struct.hpp:19,
                 from karmaTest.cpp:5:
/usr/include/boost/spirit/home/karma/nonterminal/rule.hpp: In instantiation of ‘static void boost::spirit::karma::rule<OutputIterator, T1, T2, T3, T4>::define(boost::spirit::karma::rule<OutputIterator, T1, T2, T3, T4>&, const Expr&, mpl_::false_) [with Auto = mpl_::bool_<false>; Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_left, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::omit>, 0l>&, boost::spirit::karma::rule<std::back_insert_iterator<std::basic_string<char> >, RowData(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2l>; OutputIterator = std::back_insert_iterator<std::basic_string<char> >; T1 = std::pair<long unsigned int, RowData>(); T2 = boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type; mpl_::false_ = mpl_::bool_<false>]’:
/usr/include/boost/spirit/home/karma/nonterminal/rule.hpp:229:19:   required from ‘boost::spirit::karma::rule<OutputIterator, T1, T2, T3, T4>& boost::spirit::karma::rule<OutputIterator, T1, T2, T3, T4>::operator=(const Expr&) [with Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_left, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::omit>, 0l>&, boost::spirit::karma::rule<std::back_insert_iterator<std::basic_string<char> >, RowData(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2l>; OutputIterator = std::back_insert_iterator<std::basic_string<char> >; T1 = std::pair<long unsigned int, RowData>(); T2 = boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’
karmaTest.cpp:54:18:   required from ‘RowDataGrammar<OutputIterator>::RowDataGrammar() [with OutputIterator = std::back_insert_iterator<std::basic_string<char> >]’
karmaTest.cpp:84:62:   required from here
/usr/include/boost/spirit/home/karma/nonterminal/rule.hpp:185:13: error: no matching function for call to ‘assertion_failed(mpl_::failed************ (boost::spirit::karma::rule<OutputIterator, T1, T2, T3, T4>::define(boost::spirit::karma::rule<OutputIterator, T1, T2, T3, T4>&, const Expr&, mpl_::false_) [with Auto = mpl_::bool_<false>; Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_left, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::omit>, 0l>&, boost::spirit::karma::rule<std::back_insert_iterator<std::basic_string<char> >, RowData(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2l>; OutputIterator = std::back_insert_iterator<std::basic_string<char> >; T1 = std::pair<long unsigned int, RowData>(); T2 = boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type; mpl_::false_ = mpl_::bool_<false>]::error_invalid_expression::************)(boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_left, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::omit>, 0l>&, boost::spirit::karma::rule<std::back_insert_iterator<std::basic_string<char> >, RowData(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2l>))’
             BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
             ^
/usr/include/boost/spirit/home/karma/nonterminal/rule.hpp:185:13: note: candidate is:
/usr/include/boost/mpl/assert.hpp:82:5: note: template<bool C> int mpl_::assertion_failed(typename mpl_::assert<C>::type)
 int assertion_failed( typename assert<C>::type );
     ^
/usr/include/boost/mpl/assert.hpp:82:5: note:   template argument deduction/substitution failed:
/usr/include/boost/spirit/home/karma/nonterminal/rule.hpp:185:13: note:   cannot convert ‘boost::spirit::karma::rule<OutputIterator, T1, T2, T3, T4>::define(boost::spirit::karma::rule<OutputIterator, T1, T2, T3, T4>&, const Expr&, mpl_::false_)::error_invalid_expression185::assert_arg<mpl_::bool_<false>, boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_left, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::omit>, 0l>&, boost::spirit::karma::rule<std::back_insert_iterator<std::basic_string<char> >, RowData(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2l> >()’ (type ‘mpl_::failed************ (boost::spirit::karma::rule<OutputIterator, T1, T2, T3, T4>::define(boost::spirit::karma::rule<OutputIterator, T1, T2, T3, T4>&, const Expr&, mpl_::false_) [with Auto = mpl_::bool_<false>; Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_left, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::omit>, 0l>&, boost::spirit::karma::rule<std::back_insert_iterator<std::basic_string<char> >, RowData(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2l>; OutputIterator = std::back_insert_iterator<std::basic_string<char> >; T1 = std::pair<long unsigned int, RowData>(); T2 = boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type; mpl_::false_ = mpl_::bool_<false>]::error_invalid_expression::************)(boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_left, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::omit>, 0l>&, boost::spirit::karma::rule<std::back_insert_iterator<std::basic_string<char> >, RowData(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2l>)’) to type ‘mpl_::assert<false>::type {aka mpl_::assert<false>}’
             BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
1
fails to compile. And what's an error message? Compiler You're using?Kamiccolo
I added the error message and I am using gcc 4.8.3.Adam Shrader
You can't use omit like that, you need to specify the generator you want to omit. Quick example (You should probably use another, more appropriate generator instead of int_)..llonesmiz

1 Answers

1
votes

As cv_and_he said, I was using omit incorrectly. An old coworker I reached out to told me the same. The corrected code is below.

main.cpp

#include <iostream>
#include <map>

#include <boost/cstdint.hpp>
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/make_tuple.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <boost/spirit/include/karma.hpp>

namespace bs = boost::spirit;

struct RowData
{
    RowData() :
        field0(0),
        field1(0),
        field2(0),
        field3(0)
    {
    }

    boost::uint64_t field0;
    boost::uint64_t field1;
    boost::uint64_t field2;
    boost::uint64_t field3;
};

BOOST_FUSION_ADAPT_STRUCT(
    RowData,
    (boost::uint64_t, field0)
    (boost::uint64_t, field1)
    (boost::uint64_t, field2)
    (boost::uint64_t, field3)
)

template <typename OutputIterator>
struct RowDataGrammar :
    bs::karma::grammar< OutputIterator, std::map<boost::uint64_t, RowData>() >
{
    RowDataGrammar() : RowDataGrammar::base_type(allRowsRule)
    {
        rowDataRule =
            bs::karma::lit("(") <<
            bs::karma::ulong_ <<
            bs::karma::lit(", ") <<
            bs::karma::ulong_ <<
            bs::karma::lit(", ") <<
            bs::karma::ulong_ <<
            bs::karma::lit(", ") <<
            bs::karma::ulong_ <<
            bs::karma::lit(")");

        // I only want the value from the map. The key is dropped.
        pairRule = bs::karma::omit[bs::karma::ulong_] << rowDataRule;

        allRowsRule = pairRule % ", ";
    }

private:
    bs::karma::rule< OutputIterator, RowData() > rowDataRule;
    bs::karma::rule< OutputIterator, std::pair<boost::uint64_t, RowData>() > pairRule;
    bs::karma::rule< OutputIterator, std::map<boost::uint64_t, RowData>() >  allRowsRule;
};

int main(int argc, char** argv)
{
    std::map<boost::uint64_t, RowData> rowMap;

    RowData rowData;
    rowData.field0 = 0;
    rowData.field1 = 1;
    rowData.field2 = 2;
    rowData.field3 = 3;
    rowMap.insert(std::make_pair(10, rowData));

    rowData.field0 = 6;
    rowData.field1 = 7;
    rowData.field2 = 8;
    rowData.field3 = 9;
    rowMap.insert(std::make_pair(20, rowData));

    std::string generatedString;
    std::back_insert_iterator<std::string> sink(generatedString);
    RowDataGrammar< std::back_insert_iterator<std::string> > grammar;

    bs::karma::generate(sink, grammar, rowMap);

    std::cout << "output :" << generatedString << std::endl;
}