Boost.Spirit.Qi - 针对原始数据类型的边界检查
Boost.Spirit.Qi - Bounds checking against primitive data types
我需要检查已解析的 qi::uint_
的值是否小于 256。
我偶然发现了一个 概述了在解析原始类型后 运行 检查的以下语法(本例中为 qi::double_
)。
raw [ double_ [_val = _1] ] [ _pass = !isnan_(_val) && px::size(_1)<=4 ]
这里,raw[...]
returns 一个指向已解析的 qi::double_
值的迭代器,最后的语义操作用于 "test" 结果值。
从前面的示例推断,我假设我可以使用类似的方法检查边界。
raw [ uint_ [_val = _1] ] [ _pass = _val<=256 ]
不幸的是,我收到以下错误。
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)
~~~~~~~~^ ~~~
文档和示例非常适合基本解析器,但随着更高级的主题开始逐渐减少;比如这个
如何从 qi::_val
转换或提取无符号整数值以针对 256 进行测试?
你错过了 raw[]
exposes an iterator range 的事实。另一个答案是因为 "extra" 约束指的是输入长度(以字符为单位)。
你不需要那个,所以你宁愿使用直接的东西,比如:
#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";
}
}
版画
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')
备注:
[action1, action2]
是提供多个语句的 Phoenix 方式(在这种情况下与 [action1][action2]
非常相似)。
您甚至可以不使用 _val=
赋值,因为这就是默认属性传播。
为了在语义操作的规则上启用默认属性传播,请使用 operator%=
来定义它:
r %= qi::double_ [ qi::_pass = (qi::_1 < 256.0) ];
打印相同的输出。
我需要检查已解析的 qi::uint_
的值是否小于 256。
我偶然发现了一个 qi::double_
)。
raw [ double_ [_val = _1] ] [ _pass = !isnan_(_val) && px::size(_1)<=4 ]
这里,raw[...]
returns 一个指向已解析的 qi::double_
值的迭代器,最后的语义操作用于 "test" 结果值。
从前面的示例推断,我假设我可以使用类似的方法检查边界。
raw [ uint_ [_val = _1] ] [ _pass = _val<=256 ]
不幸的是,我收到以下错误。
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)
~~~~~~~~^ ~~~
文档和示例非常适合基本解析器,但随着更高级的主题开始逐渐减少;比如这个
如何从 qi::_val
转换或提取无符号整数值以针对 256 进行测试?
你错过了 raw[]
exposes an iterator range 的事实。另一个答案是因为 "extra" 约束指的是输入长度(以字符为单位)。
你不需要那个,所以你宁愿使用直接的东西,比如:
#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";
}
}
版画
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')
备注:
[action1, action2]
是提供多个语句的 Phoenix 方式(在这种情况下与[action1][action2]
非常相似)。您甚至可以不使用
_val=
赋值,因为这就是默认属性传播。为了在语义操作的规则上启用默认属性传播,请使用
operator%=
来定义它:r %= qi::double_ [ qi::_pass = (qi::_1 < 256.0) ];
打印相同的输出。