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
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:
Note that this works on Boost 1.47. I would suspect it would fail on earlier versions.
Those are rather old. You should consider upgrading. Boost is up to 1.47 now.