【问题标题】:Boost, spirit, qi : how to omit attribute in a ruleBoost, Spirit, qi:如何在规则中省略属性
【发布时间】:2017-07-30 17:22:33
【问题描述】:

我有点困惑如何定义传递给qi::parse() 的spirit::qi 规则应该省略第一个“,”的出现。说,我使用以下编译代码:

std::string out_str; int out_int;
std::string s2(",345");
bool rc = qi::parse(s2.begin(), s2.end(), qi::omit[qi::lit(",")] >>
                                          qi::int_, out_int);

但代码没有:

bool rc = qi::parse(s2.begin(), s2.end(), qi::omit[qi::lit(",")] >>
                                          qi::as_string[*qi::digit], out_str);

发射错误: boost\boost_1_64_0\boost\spirit\home\qi\detail\assign_to.hpp(153): error C2440: 'static_cast': cannot convert from 'const std::string' to 'char'

有人可以帮我理解我做错了什么吗?

【问题讨论】:

  • IIRC,lit 不合成属性,所以 omit 似乎是多余的。
  • 你是对的。但是更改为 qi::omit[qi::char_] >> qi::as_string[*qi::digit] 对我也不起作用。
  • 类似地,*qi::digit 的合成属性将是一个字符序列。这已经可以分配给std::string,因此这里也没有理由使用as_string。只需将语法写成qi::lit(",") >> *qi::digit -- wandbox.org/permlink/HGd0VTxt1i6jrkAX
  • 工作正常,谢谢丹!

标签: boost boost-spirit-qi


【解决方案1】:

假设您真的只是想解析一个整数列表,其中一些元素可能会丢失,只需按您的意愿拼写即可:

-uint_ % ','

就是这样。它可以很好地解析为 vector<T>,其中 T 是一个适合您的应用程序域的整数类型。

演示

Live On Wandbox

#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;

int main() {
    for (std::string const input : {"", ",", ",345", "1,,2,3,4,"}) {
        std::vector<int> the_important_stuff;
        bool ok = qi::parse(input.begin(), input.end(), -qi::uint_ % ',', the_important_stuff);

        if (ok)
            std::cout << "Input '" << input << "' parsed into " << the_important_stuff.size() << " integers\n";
        else
            std::cout << "Input '" << input << "' failed to parse\n";
    }
}

打印出来的

Input '' parsed into 0 integers
Input ',' parsed into 0 integers
Input ',345' parsed into 1 integers
Input '1,,2,3,4,' parsed into 4 integers

奖金

忽略任何无关紧要的空格(即不在数字内),将调用更改为

    bool ok = qi::phrase_parse(input.begin(), input.end(), -qi::uint_ % ',', qi::space, the_important_stuff);

【讨论】:

  • 感谢您的回答,但重点是我不需要矢量。说,我有一个字符串,用“,”分隔固定长度的单词(例如:“#B7C82,33,9991,10!”,其中B7C82-id,“33”-应该是一个固定长度= 2的字符串,“ 9991" - 应该是一个固定长度 = 4 的字符串,等等)。我知道我可以通过验证生成的属性长度在语义操作中设置 qi::_pass=false,但我更喜欢 qi::lit(",") >> qi::repeat(2)[qi::char_ ] >> qi::lit(",")。老实说,我仍然很困惑为什么 qi::as_string[] 会破坏编译。
  • 容器属性非常灵活。您可以有许多子表达式来构建单个容器属性,这确实会导致歧义/错误的启发式方法。但是,您仍然想要表达语法的意图,而不是“如何”。这意味着您应该简单地写qi::uint_parser&lt;int, 10, 2, 2&gt; 而不是qi::repeat(2)[qi::char_]The documentation says that qi::as_string` 合成一个字符容器,这不是你需要的。
  • 附带说明:如果您需要一堆东西的字符串源,请将其包装在qi::raw(例如raw[int_ % ','])中。
  • 感谢有关 qi::raw 的提示!现场工作示例:here。但是,我仍然只能猜测为什么 qi::raw[qi::uint_parser{}] 发出只有第一个字符的属性,因为 qi::raw 应该返回一个范围。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-28
相关资源
最近更新 更多