Carbon
Carbon

Reputation: 3943

Boost::spirit::qi - How do I build a parse rule that sets a property?

I'd like to build a rule that takes in a few parameters from a parsed line then sets a few as constant. Is that possible? An (invalid) example to illustrate what I'm trying to do is below. I think I'm using _r1 incorrectly here, but I'm not sure how to get at the right thing. Assume I don't want to just modify r before sending it into the parser.

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_plus.hpp>
#include <boost/spirit/include/qi_sequence.hpp>
#include <boost/spirit/include/qi_string.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/phoenix/bind/bind_function.hpp>
#include <string>

using namespace boost::spirit::qi;
struct Sample
{
    int a;
    int b;
};
BOOST_FUSION_ADAPT_STRUCT(Sample, a , b)

const rule<std::string::const_iterator, Sample()> AnythingAndOne = int_ >> eps[_r1.b = 1] >> eoi;


int main()
{
    std::string z("3");
    Sample r;
    parse(z.begin(), z.end(), AnythingAndOne, r);
    return 0;
}

Upvotes: 1

Views: 100

Answers (1)

sehe
sehe

Reputation: 392833

Again, with reference to Boost Spirit: "Semantic actions are evil"? I'd avoid the semantic action.

You can directly synthesize a particular attribute value by using qi::attr:

Live On Coliru

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

struct Sample {
    int a;
    int b;
};
BOOST_FUSION_ADAPT_STRUCT(Sample, a , b)

namespace qi = boost::spirit::qi;

int main()
{
    std::string const z("3");
    Sample r;
    qi::rule<std::string::const_iterator, Sample()> AnythingAndOne
         = qi::int_ >> qi::attr(1) >> qi::eoi;

    if (parse(z.begin(), z.end(), AnythingAndOne, r))
        std::cout << "Parsed: " << boost::fusion::as_vector(r) << "\n";
    else
        std::cout << "Parse failed\n";
}

Prints

Parsed: (3 1)

Upvotes: 1

Related Questions