Boost Spirit 语法匹配嘈杂的输入

发布于 2024-12-13 11:32:49 字数 881 浏览 2 评论 0原文

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

我想要的数据如下。

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

我想确保该事件属于新状态类型。

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

到目前为止,我已经得到了:

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 version 1.42 compiler g++ 4.4 Spirit 0x2020

I am trying to parse a noisy input, ideally I would be able to see whether a stanza matchs the rule and if it does get the data I need and discard the rest.

The data I want is as follows.

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

I want to make sure that Event if of type new state.

And I need the channel state. The rest I don't care about (just yet) so I want to ignore it, I want it to be flexible and accept any old crap bettween the important stuff, really i don't want to say ignore this line, but rather ignore anything between Event and the end of channel state where I capture the value.

So far I have got:

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_ ];

but this isn't working for some reason, I always get false back when I do this:

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

EDIT: Boost version 1.42 compiler g++ 4.4 Spirit 0x2020

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

拒绝两难 2024-12-20 11:32:49

请记住:Spirit 的解析器是贪婪的。这意味着如果您执行 qi::omit[; ],它将继续省略字符,直到不再满足。由于 实际上是 任何东西char_ 匹配任何字符,因此 *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了。

Remember: Spirit's parser is greedy. Which means that if you do qi::omit[ <something> ], it will continue to omit characters until the <something> is no longer met. Since <something> is literally anything (char_ matches any character, so *char_ matches all characters), it will eat the entire rest of the string. Then it will raise an error, because it never got to "ChannelState: ".

Your way of doing it simply won't work. You have to have some cut-off switch to stop the *char_ from eating everything.

I don't see why you don't just parse them all into a std::map, rather than doing it piecemeal. Then you can just pick out the elements you want. You say that you don't want some elements yet, so just ignore them.

This would be done as follows:

//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); 

Note that this works on Boost 1.47. I would suspect it would fail on earlier versions.

Boost version 1.42 compiler g++ 4.4 Spirit 0x2020

Those are rather old. You should consider upgrading. Boost is up to 1.47 now.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文