问题
I need to check that the value of a parsed qi::uint_
is less than 256.
I stumbled across an SO post outlining the following syntax to run checks after a primitive type has been parsed (qi::double_
in this example).
raw [ double_ [_val = _1] ] [ _pass = !isnan_(_val) && px::size(_1)<=4 ]
Here, raw[...]
returns an iterator to the parsed qi::double_
value, and the final semantic action is used to "test" the resulting value.
Extrapolating from the previous example, I assumed I could check bounds using a similar approach.
raw [ uint_ [_val = _1] ] [ _pass = _val<=256 ]
Unfortunately, I get the following error.
boost.spirit.qi.bounds.cpp:51:105: error: invalid operands to binary expression ('const boost::spirit::_val_type'
(aka 'const actor<attribute<0> >') and 'int')
if (qi::parse(str.begin(), str.end(), qi::raw[qi::uint_[qi::_val = qi::_1]][qi::_pass = qi::_val<=256]).full)
~~~~~~~~^ ~~~
The documentation and examples are great for basic parsers, but it begins to taper off with more advanced topics; such as this.
How can I convert or extract the unsigned integer value from qi::_val
to test against 256?
回答1:
You have missed the fact that raw[] exposes an iterator range. The other answer used that because the "extra" constraint was referring to the input length (in characters).
You don't need that, so you'd rather use something direct like:
Live On Coliru
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <iostream>
namespace qi = boost::spirit::qi;
int main ()
{
using It = std::string::const_iterator;
qi::rule<It, double()> r
= qi::double_ [ qi::_pass = (qi::_1 < 256.0), qi::_val = qi::_1 ];
for (std::string const s: { "1.23", ".123", "2.e6", "inf", "-inf", "3.2323", "nan" })
{
It f = s.begin(), l = s.end();
double result;
if (parse(f, l, r, result))
std::cout << "accepted: '" << s << "' -> " << result;
else std::cout << "rejected: '" << s << "'";
if (f!=l)
std::cout << " (remaining: '" << std::string(f,l) << "')\n";
else std::cout << "\n";
}
}
Prints
accepted: '1.23' -> 1.23
accepted: '.123' -> 0.123
rejected: '2.e6' (remaining: '2.e6')
rejected: 'inf' (remaining: 'inf')
accepted: '-inf' -> -inf
accepted: '3.2323' -> 3.2323
rejected: 'nan' (remaining: 'nan')
Notes:
the
[action1, action2]
is the Phoenix way of supplying multiple statements (in this case would be very similar to[action1][action2]
).you can even do without the
_val=
assignment, because that's just what default attribute propagation is.In order to enable default attribute propagation on a rule that semantic action(s), use
operator%=
to define it:r %= qi::double_ [ qi::_pass = (qi::_1 < 256.0) ];
Live On Coliru
That prints the same output.
来源:https://stackoverflow.com/questions/51272067/boost-spirit-qi-bounds-checking-against-primitive-data-types