[Spirit]Kleene star with arguments having optional attributes.

Hello Boost Users, I'm now building configuration file parser with Boost.Spirit. I have a little trouble understanding how this parser builds attribute: It was supposed to parse strings throwing 'p' letter away. *((qi::char_ - 'p') | qi::lit('p')) attribute of qi::lit is Unused. attribute of (qi::char_ - 'p') is char. so attribute of ((qi::char_ - 'p') | qi::lit('p')) should be optional<char> that is uninitialized optional value when matched against character 'p' After applying Kleene star it should became vector<optional<char> >. It seems to be compatible with string (at least it compiles). But 'p' letters are not thrown away. The full example is here: http://pastebin.com/tCMw22Zy The output of that example is: Full parsing Result: "abcpppdef" Is it possible to make such a parser without using semantic actions like [bind(&string::append, res, _1)] or something like that, which seem to be less elegant solution. Thanks!

I've suddenly found a solution like this: *((qi::char_ - 'p') >> qi::omit[*qi::lit('p')]) But nevertheless it is interesting for me why my first attempt was wrong and how should I understand its behavior. Thanks. On 24 November 2010 13:06, Paul Graphov <graphov@gmail.com> wrote:
Hello Boost Users,
I'm now building configuration file parser with Boost.Spirit. I have a little trouble understanding how this parser builds attribute:
It was supposed to parse strings throwing 'p' letter away.
*((qi::char_ - 'p') | qi::lit('p'))
attribute of qi::lit is Unused. attribute of (qi::char_ - 'p') is char.
so attribute of ((qi::char_ - 'p') | qi::lit('p')) should be optional<char> that is uninitialized optional value when matched against character 'p'
After applying Kleene star it should became vector<optional<char> >. It seems to be compatible with string (at least it compiles). But 'p' letters are not thrown away.
The full example is here: http://pastebin.com/tCMw22Zy
The output of that example is: Full parsing Result: "abcpppdef"
Is it possible to make such a parser without using semantic actions like [bind(&string::append, res, _1)] or something like that, which seem to be less elegant solution.
Thanks!

2010/11/24, Paul Graphov <graphov@gmail.com>:
Is it possible to make such a parser without using semantic actions like [bind(&string::append, res, _1)] or something like that, which seem to be less elegant solution.
The following works as expected: std::vector<boost::optional<char> > vec; bool r = qi::parse(begin, end, *('p' | qi::char_), vec); Why std::string does not? I have no idea, either. You can go to https://lists.sourceforge.net/lists/listinfo/spirit-general for more specific help.

Thanks, I didn't know that there is a dedicated Spirit mailing list. On 24 November 2010 15:49, TONGARI <tongari95@gmail.com> wrote:
2010/11/24, Paul Graphov <graphov@gmail.com>:
Is it possible to make such a parser without using semantic actions like [bind(&string::append, res, _1)] or something like that, which seem to be less elegant solution.
The following works as expected:
std::vector<boost::optional<char> > vec; bool r = qi::parse(begin, end, *('p' | qi::char_), vec);
Why std::string does not? I have no idea, either.
You can go to https://lists.sourceforge.net/lists/listinfo/spirit-general for more specific help. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

BTW, you can use qi::skip in this case: bool r = qi::parse(begin, end, qi::skip('p')[*qi::char_], res); it seems well-suited here. 2010/11/24, Paul Graphov <graphov@gmail.com>:
Thanks, I didn't know that there is a dedicated Spirit mailing list.
On 24 November 2010 15:49, TONGARI <tongari95@gmail.com> wrote:
2010/11/24, Paul Graphov <graphov@gmail.com>:
Is it possible to make such a parser without using semantic actions like [bind(&string::append, res, _1)] or something like that, which seem to be less elegant solution.
The following works as expected:
std::vector<boost::optional<char> > vec; bool r = qi::parse(begin, end, *('p' | qi::char_), vec);
Why std::string does not? I have no idea, either.
You can go to https://lists.sourceforge.net/lists/listinfo/spirit-general for more specific help. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

From: boost-users-bounces@lists.boost.org on behalf of TONGARI Sent: Wed 11/24/2010 7:49 AM To: boost-users@lists.boost.org Subject: Re: [Boost-users] [Spirit]Kleene star with arguments havingoptional attributes.
2010/11/24, Paul Graphov <graphov@gmail.com>: Is it possible to make such a parser without using semantic actions like [bind(&string::append, res, _1)] or something like that, which seem to be less elegant solution.
The following works as expected:
std::vector<boost::optional<char> > vec; bool r = qi::parse(begin, end, *('p' | qi::char_), vec);
Why std::string does not? I have no idea, either.
If you can in the future providing a stand alone example describing a problem is very helpful in giving you a good answer. What I see from the simple grammar is that you are looking for a sequence of characters. The 'qi::char_' will parse any single character (see http://www.boost.org/doc/libs/1_45_0/libs/spirit/doc/html/spirit/qi/referenc...). The 'p' is a qi literal which is not meant to be parsed into the output string. I found in a simple example I used below that the 'p' character was placed in the output. I think the | operator used the qi::char_ to parse the 'p' character. Here is my example which places the parsed input string into a std::string. What is happening beneath the code is that the sequence of zero or more characters is that is being placed into a std::vector<char> which happens to be automatically promoted into a std::string. Since I did not have the original email does this solve your problem? Stephen ------------------- #include <boost/spirit/home/qi.hpp> #include <iostream> int main (int, char**) { std::string input = "apapa"; std::string::const_iterator begin = input.begin(); std::string::const_iterator end = input.end(); std::string output; bool r = boost::spirit::qi::parse ( begin, end, *(boost::spirit::qi::lit('p')|boost::spirit::qi::char_), output ); if ( r ) { std::cout << "Success: found - " << output << std::endl; } else { std::cout << "Failed to parse string" << std::endl; } return 0; }

Thanks for the answers. Stephen, you can look at original emails here: http://thread.gmane.org/gmane.comp.lib.boost.user/63995 The problem is solved although I don't yet understand that strange conversion from vector<optional<char> > to string. Maybe I'll ask Spirit mailing list. qi::skip seems to be the best solution, thanks!
participants (3)
-
Paul Graphov
-
TONGARI
-
Torri, Stephen CIV NSWCDD, W15