1

Assume I already have a struct that looks like this:

struct LETTER
{
    double one;
    char[12] two;
    double three;
    char[12] four;
};

And my inputs are comma separated, for example:

"32,CATSANDDOGS,42,WHAT"
"43,BATANDZEBRAS,23,PARROT"

I've been trying to adapt this example (Spirit Qi : rule for char [5]) to to roll through BOOST_FUSION_ADAPT_STRUCT but haven't had any luck. I tried using std::array as shown here (http://www.boost.org/doc/libs/1_64_0/libs/spirit/example/qi/boost_array.cpp) but I haven't been able to make it work in a struct. Is what I'm trying to do even possible? What am I doing wrong here? I would think this would be the most obvious use case.

Is what I'm trying to do even possible?

Carbon
  • 3,828
  • 3
  • 24
  • 51
  • The most obvious use case uses fixed-size char arrays? That's most obvious in 1970's C. Just use `std::string` if you're after the obvious use cases – sehe Nov 28 '17 at 14:25

1 Answers1

1

I'm going to assume you want to write idiomatic C++ code (which is obviously the target domain for Spirit Qi), so you can use std::string:

Live On Coliru

#include <boost/fusion/adapted.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iostream>

namespace qi = boost::spirit::qi;

struct Letter {
    double one;
    std::string two;
    double three;
    std::string four;
};

BOOST_FUSION_ADAPT_STRUCT(Letter, one, two, three, four)

template <typename Iterator> struct LETTERParser : qi::grammar<Iterator, Letter()> {
    LETTERParser() : LETTERParser::base_type(start) {
        using namespace qi;

        _11c = repeat(11) [char_];
        start = skip(space) [ "LETTER" >> double_ >> _11c >> double_ >> _11c ];
    }
  private:
    qi::rule<Iterator, Letter()> start;
    qi::rule<Iterator, std::string()> _11c;
};

int main() {
    const std::string input("LETTER 42 12345678901 +Inf abcdefghijk  ");
    using It = std::string::const_iterator;

    LETTERParser<It> parser;
    Letter example;

    It f = input.begin(), l = input.end();

    if (phrase_parse(f, l, parser, qi::ascii::space, example)) {
        std::cout << "parsed: " << boost::fusion::as_vector(example) << "\n";
        std::cout << " example.one: " << example.one << "\n";
        std::cout << " example.two: '" << example.two << "'\n";
        std::cout << " example.three: " << example.three << "\n";
        std::cout << " example.four: '" << example.four << "'\n";
    } else {
        std::cout << "couldn't parse '" << input << "'\n";
    }

    if (f != l)
        std::cout << "Remaining unparsed input: '" << std::string(f,l) << "'\n";
}

Prints

parsed: (42 12345678901 inf abcdefghijk)
 example.one: 42
 example.two: '12345678901'
 example.three: inf
 example.four: 'abcdefghijk'
sehe
  • 374,641
  • 47
  • 450
  • 633