Boost Spirit rule with custom attribute parsing
I am writing a Boost Spirit grammar to parse text into a vector of these structs:
struct Pair
{
double a;
double b;
};
BOOST_FUSION_ADAPT_STRUCT(
Pair,
(double, a)
(double, a)
)
This gr开发者_如何学Goammar has a rule like this:
qi::rule<Iterator, Pair()> pairSequence;
However, the actual grammar of pairSequence
is this:
double_ % separator
I want this grammar to produce a Pair
with a
equal to the double and b
equal to some constant. I want to do something like this:
pairSequence = double_[_val = Pair(_1, DEFAULT_B)] % separator;
The above does not compile, of course. I tried adding a constructor to Pair
, but I still get compile errors (no matching function for call to 'Pair::Pair(const boost::phoenix::actor >&, double)').
First of all, the signature of pairSequence
needs to be:
qi::rule<Iterator, std::vector<Pair>()> pairSequence;
as the list operator exposes a std::vector<Pair>
as its attribute.
All functions called from inside a semantic action have to be 'lazy', so you need to utilize phoenix:
namespace phx = boost::phoenix;
pairSequence =
double_[
phx::push_back(_val,
phx::construct<Pair>(_1, phx::val(DEFAULT_B))
)
] % separator
;
Another possibility would be to add a (non-explicit) constructor to Pair
:
struct Pair
{
Pair(double a) : a(a), b(DEFAULT_B) {}
double a;
double b;
};
which allows to simplify the grammar:
pairSequence = double_ % separator;
and completely relies on Spirit's built-in attribute propagation rules.
BTW, for any of this to work, you don't need to adapt Pair
as a Fusion sequence.
精彩评论