Boost.Spirit.Qi-针对原始数据类型的边界检查

时间:2018-07-10 18:38:16

标签: c++ bounds boost-spirit-qi

我需要检查已解析的qi::uint_的值是否小于256。


我偶然发现了SO post,概述了以下语法以在解析原始类型后运行检查(在本示例中为qi::double_)。

raw [ double_ [_val = _1] ] [ _pass = !isnan_(_val) && px::size(_1)<=4 ]

在这里,raw[...]将迭代器返回到解析后的qi::double_值,最后的语义操作用于“测试”结果值。


从上一个示例推算出,我假设我可以使用类似的方法来检查边界。

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进行测试?

1 个答案:

答案 0 :(得分:2)

您错过了raw[] exposes an iterator range的事实。另一个答案是因为“额外”约束是指输入长度(以字符为单位)。

您不需要它,所以您宁愿直接使用类似的东西:

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";
    }
}

打印

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')

注意:

  1. [action1, action2]是Phoenix提供多个语句的方式(在这种情况下,它与[action1][action2]非常相似)。

  2. 您甚至可以不用分配_val=,因为这就是默认属性传播的方式。

    为了在语义动作的规则上启用默认属性传播,请使用operator%=对其进行定义:

    r %= qi::double_ [ qi::_pass = (qi::_1 < 256.0) ];
    

    Live On Coliru

    输出相同的输出。