struct coordinate {
int x;
int y;
int z;
};
BOOST_FUSION_ADAPT_STRUCT(
coordinate,
(int, x)
(int, y)
(int, z)
)
template <typename Iterator>
struct coordinate_grammar : qi::grammar<Iterator, coordinate(), ascii::space_type>
{
coordinate_grammar()
:
coordinate_grammar::base_type(start),
optional_x(-(qi::int_ >> ':')),
optional_z(-('@' >> qi::int_)),
start(optional_x >> qi::int_ >> optional_z)
{
}
qi::rule<Iterator, int, ascii::space_type> optional_x;
qi::rule<Iterator, int, ascii::space_type> optional_z;
qi::rule<Iterator, coordinate(), ascii::space_type> start;
};
I would like to set 0
as the default value of x
, and 1000
as the default value of z
.
Input --> Desired Output:
200:400@300
--> [200,400,300]
200:400
--> [200,400,1000]
400@300
--> [0,400,300]
400
--> [0,400,1000]
How do I need to modify the rule syntax to provide a default value when a value has not been specified for the optional (optional_x
and optional_z
) parsers?
The trick is to reconsider the notion of "optional"...
optional_x(-(qi::int_ >> ':')),
optional_z(-('@' >> qi::int_)),
As we know, the -
prefix indicates this rule can be specified 0 or 1 times, thus making it optional.
However, we don't actually want to have an "optional" value. We want either the value that has been parsed OR a default value. This is not optional, it is quite simply one or the other.
By modifying the rule syntax, when can better describe our intent.
optional_x((qi::int_ >> ':') | qi::attr(0)),
optional_z(('@' >> qi::int_) | qi::attr(1000)),
Now when the option is processed, if you have not provided a value for x
or z
, then a value will be provided on your behalf by qi:attr(...)
.