看来我已经很接近了,即只需对 double_ 解析器进行一些更改,我就完成了。这可能比添加新语法更易于维护,因为所有其他解析都是通过这种方式完成的。 – 携带7 小时前 https://stackoverflow.com/questions/30375750/extending-the-existing-boost-spirit-real-parser-with-a-policy-plus-a-wrapped-par#comment48844034_30375750
更可维护的是根本不编写另一个解析器。
您基本上想要解析浮点数(精神已覆盖你)但随后应用一些验证。我会在语义操作中进行验证:
raw [ double_ [_val = _1] ] [ _pass = !isnan_(_val) && px::size(_1)<=4 ]
就是这样。
说明
Anatomy:
现在唯一剩下的就是将它们绑在一起。让我们制作一个延迟版本::isnan
:
boost::phoenix::function<decltype(&::isnan)> isnan_(&::isnan);
我们就可以出发了。
测试程序
Live On Coliru http://coliru.stacked-crooked.com/a/3d352fca049d6e8b
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <cmath>
#include <iostream>
int main ()
{
using It = std::string::const_iterator;
auto my_fpnumber = [] { // TODO encapsulate in a grammar struct
using namespace boost::spirit::qi;
using boost::phoenix::size;
static boost::phoenix::function<decltype(&::isnan)> isnan_(&::isnan);
return rule<It, double()> (
raw [ double_ [_val = _1] ] [ _pass = !isnan_(_val) && size(_1)<=4 ]
);
}();
for (std::string const s: { "1.23", ".123", "2.e6", "inf", "3.2323", "nan" })
{
It f = s.begin(), l = s.end();
double result;
if (parse(f, l, my_fpnumber, result))
std::cout << "Parse success: '" << s << "' -> " << result << "\n";
else
std::cout << "Parse rejected: '" << s << "' at '" << std::string(f,l) << "'\n";
}
}
Prints
Parse success: '1.23' -> 1.23
Parse success: '.123' -> 0.123
Parse success: '2.e6' -> 2e+06
Parse success: 'inf' -> inf
Parse rejected: '3.2323' at '3.2323'
Parse rejected: 'nan' at 'nan'
1 必须在此处显式完成分配,因为我们使用语义操作,并且它们通常会抑制自动属性传播