boost::spirit 解析带分隔符号的双精度数
boost::spirit parsing double with separated sign
我正在使用 boost::spirit 将文本解析为双打,其单音可能会用空格与数字分开。
使用或误用 real_policies,我找到了一个解决方案,但我不确定是否有更简单的方法来实现它。
有人可以给我提示吗?
这里是相关的代码片段:
template <typename T>
struct real_with_separated_sign_policies : boost::spirit::qi::real_policies<T>
{
// allow skipping chars between a possible sign and a folling real number
template <typename Iterator>
static bool parse_sign(Iterator& first, Iterator const& last)
{
bool ret = qi::extract_sign(first, last);
if (ret)
qi::parse(first, last, *qi::lit(' '));
return ret;
}
};
template <typename Iterator, typename Skipper>
struct RealWithSeparatedSignParser
: qi::grammar<Iterator, double(), Skipper>
{
boost::spirit::qi::real_parser<double, real_with_separated_sign_policies<double> > RealWithSeparatedSignValue;
RealWithSeparatedSignParser() : RealWithSeparatedSignParser::base_type(start)
{
start %= RealWithSeparatedSignValue;
}
qi::rule<Iterator, double(), Skipper> start;
};
int main() {
std::string str = " - 1.234 ";
我会像您在这里那样做。您应该考虑恢复 first
迭代器以防进一步解析失败。
您可能需要仔细检查 multi_pass<>
适配迭代器的刷新语义(我认为这没关系,因为包装 real_parser
无论如何都必须能够在失败时回溯)。
当然,鉴于语法的简单性,样本可以减少,但我想这不是重点。
这是一个更短的演示,展示了更通用的跳过策略(默认使用 blank_type
):
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
template <typename T, typename Skipper = qi::blank_type>
struct skip_after_sign_policies : boost::spirit::qi::real_policies<T> {
// allow skipping chars between a possible sign and a folling real number
template <typename Iterator>
static bool parse_sign(Iterator& first, Iterator const& last) {
return qi::extract_sign(first, last)
&& qi::phrase_parse(first, last, qi::eps, Skipper {});
}
};
int main() {
qi::real_parser<double, skip_after_sign_policies<double> > grammar;
std::string const str = " - 1.234 ";
auto it = str.begin();
double value;
bool ok = phrase_parse(it, str.end(), grammar, qi::space, value);
std::cout << std::boolalpha << ok << " " << value;
if (it != str.end())
std::cout << "Remaining: '" << std::string(it, str.end()) << "'\n";
}
版画
true -1.234
我正在使用 boost::spirit 将文本解析为双打,其单音可能会用空格与数字分开。
使用或误用 real_policies,我找到了一个解决方案,但我不确定是否有更简单的方法来实现它。 有人可以给我提示吗?
这里是相关的代码片段:
template <typename T>
struct real_with_separated_sign_policies : boost::spirit::qi::real_policies<T>
{
// allow skipping chars between a possible sign and a folling real number
template <typename Iterator>
static bool parse_sign(Iterator& first, Iterator const& last)
{
bool ret = qi::extract_sign(first, last);
if (ret)
qi::parse(first, last, *qi::lit(' '));
return ret;
}
};
template <typename Iterator, typename Skipper>
struct RealWithSeparatedSignParser
: qi::grammar<Iterator, double(), Skipper>
{
boost::spirit::qi::real_parser<double, real_with_separated_sign_policies<double> > RealWithSeparatedSignValue;
RealWithSeparatedSignParser() : RealWithSeparatedSignParser::base_type(start)
{
start %= RealWithSeparatedSignValue;
}
qi::rule<Iterator, double(), Skipper> start;
};
int main() {
std::string str = " - 1.234 ";
我会像您在这里那样做。您应该考虑恢复 first
迭代器以防进一步解析失败。
您可能需要仔细检查 multi_pass<>
适配迭代器的刷新语义(我认为这没关系,因为包装 real_parser
无论如何都必须能够在失败时回溯)。
当然,鉴于语法的简单性,样本可以减少,但我想这不是重点。
这是一个更短的演示,展示了更通用的跳过策略(默认使用 blank_type
):
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
template <typename T, typename Skipper = qi::blank_type>
struct skip_after_sign_policies : boost::spirit::qi::real_policies<T> {
// allow skipping chars between a possible sign and a folling real number
template <typename Iterator>
static bool parse_sign(Iterator& first, Iterator const& last) {
return qi::extract_sign(first, last)
&& qi::phrase_parse(first, last, qi::eps, Skipper {});
}
};
int main() {
qi::real_parser<double, skip_after_sign_policies<double> > grammar;
std::string const str = " - 1.234 ";
auto it = str.begin();
double value;
bool ok = phrase_parse(it, str.end(), grammar, qi::space, value);
std::cout << std::boolalpha << ok << " " << value;
if (it != str.end())
std::cout << "Remaining: '" << std::string(it, str.end()) << "'\n";
}
版画
true -1.234