1

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;
}
Carbon
  • 3,828
  • 3
  • 24
  • 51
  • `_r1` is a placeholder for an [inherited attribute](http://www.boost.org/doc/libs/1_65_1/libs/spirit/doc/html/spirit/abstracts/attributes/nonterminal_attributes.html). You don't declare any inherited attribute. What did you mean here? – sehe Dec 06 '17 at 20:03
  • I meant to parse one int, then set the other int to a constant value (one in this case). So I'd get back Sample a = {3,1} from "3". – Carbon Dec 06 '17 at 20:04
  • Can you do that by adding a fixed int to the tuple in the rule? – Carbon Dec 06 '17 at 20:04
  • Sure. I'd be a lot simpler. Thanks clarifying. Posting in a few minutes – sehe Dec 06 '17 at 20:05
  • Thanks man, you've really helped out. – Carbon Dec 06 '17 at 20:05

1 Answers1

1

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)
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Perfect. This solves what I was getting at. I don't expect to use it, but just so I know how, how do you do it with a semantic action? – Carbon Dec 06 '17 at 20:11
  • (The non-semantic action version will go in the prod code, obviously) – Carbon Dec 06 '17 at 20:12
  • For fun, a more complicated example: [showing how you can achieve quite complex logic without actions](http://coliru.stacked-crooked.com/a/b501825f851deecc). With semantic actions, the regular place holder `qi::_1` refers to the subject parser, `qi::val` refers to the declared attribute, and all actions need to be deferred actors, e.g. [this equivalent demo using semantic actions](http://coliru.stacked-crooked.com/a/6f37a307e2d847c5) – sehe Dec 06 '17 at 20:17
  • Oh yeah, no I'm quite aware of the games you can play with ors in parsers. That's why I love this kind of stuff. – Carbon Dec 06 '17 at 20:18
  • OHHHHH USING THE NAMESPACE Now I get it. – Carbon Dec 06 '17 at 20:21
  • I was distracted earlier, noting I forgot about [using `operator%=`](http://www.boost.org/doc/libs/1_62_0/libs/spirit/doc/html/spirit/qi/reference/nonterminal/rule.html#spirit.qi.reference.nonterminal.rule.expression_semantics) in the presence of semantic actions: [better now](http://coliru.stacked-crooked.com/a/c28d18c424d776ce) - sorry for the delay – sehe Dec 06 '17 at 20:26