【问题标题】:Boost spirit grammar match noisy inputBoost Spirit 语法匹配嘈杂的输入
【发布时间】:2011-11-04 15:48:21
【问题描述】:

我正在尝试解析嘈杂的输入,理想情况下我将能够查看一个节是否符合规则,以及它是否确实获得了我需要的数据并丢弃其余数据。

我要的数据如下。

Event: Newstate
Channel: SIP/104-000001bb
ChannelState: 6
ChannelStateDesc: Up

我想确保 Event if 属于新状态。

我需要频道状态。其余的我不关心(只是还)所以我想忽略它,我希望它灵活并接受重要内容之间的任何旧废话,真的我不想说忽略这条线,而是忽略事件和我捕获值的通道状态结束之间的任何内容。

到目前为止,我得到了:

typedef boost::fusion::vector2<std::string, std::string> vect;
qi::rule<std::string::iterator, vect(), space> rule_ =
            lit("Event: ")      >> *char_("a-zA-Z") >>  
            qi::omit[ *char_ ]  >>  
            "ChannelState: "    >> *char_("0-9")    >>  
            qi::omit[ *char_ ];

但这由于某种原因不起作用,当我这样做时,我总是得到错误的回报:

vect v;
bool r=qi::parse(it, str.end(), rule_, v); 

编辑:Boost 版本 1.42 编译器 g++ 4.4 Spirit 0x2020

【问题讨论】:

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


    【解决方案1】:

    记住:Spirit 的解析器是贪婪的。这意味着如果您执行qi::omit[ &lt;something&gt; ],它将继续省略字符,直到不再满足&lt;something&gt;。因为&lt;something&gt; 字面上是anythingchar_ 匹配任何字符,所以*char_ 匹配所有字符),它将吃掉整个字符串的其余部分。然后它会引发一个错误,因为它永远不会到达“ChannelState:”。

    你这样做的方式根本行不通。你必须有一些切断开关来阻止*char_ 吃掉所有东西。

    我不明白您为什么不将它们全部解析为std::map,而不是零碎地进行。然后你可以选择你想要的元素。你说你不想要一些元素,所以忽略它们。

    这将按如下方式完成:

    //Includes
    #include <boost/spirit/include/qi.hpp>
    #include <boost/fusion/adapted/std_pair.hpp>
    
    //Code
    using namespace boost::spirit;
    using ascii::char_;
    using ascii::string;
    
    qi::rule<std::string::iterator, std::pair<std::string, std::string>() > pair_rule =
      *(char_ - ':') >> ':' >>
      qi::omit[*ascii::space] >>
      *(char_ - eol) >> (eol || eoi);
    
    qi::rule<std::string::iterator, std::map<std::string, std::string>() > map_rule =
      +pair_rule;
    
    std::map<std::string, std::string> v;
    bool r = qi::parse(test.begin(), test.end(), map_rule, v); 
    

    请注意,这适用于 Boost 1.47。我怀疑它在早期版本上会失败。

    Boost 版本 1.42 编译器 g++ 4.4 Spirit 0x2020

    那些都比较老了。你应该考虑升级。 Boost 现在高达 1.47。

    【讨论】:

    • 感谢您的回复,我明天回去工作时必须试一试。我知道这些版本很旧,但我必须确保它在永远存在于过去的当前 debian 版本(挤压)上编译:(
    • @111111:即使 std::pairstd::map 的东西在旧版本上不起作用,您也可以随时更改属性以存储包含两个 @ 的结构的 std::vector 987654332@s.
    • 是的,无论如何我都想这样做,因为最多只有 15 个元素我会认为 std::map 的开销会很浪费。跨度>
    猜你喜欢
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-04
    • 2011-01-11
    • 2012-02-28
    • 2011-03-05
    相关资源
    最近更新 更多