Re: How to use spirit's qi attributes properly
Henri Menke <[email protected]> Wed, 30 May 2018 11:57:43 +1200
| Newsgroups | gmane.comp.parsers.spirit.general |
|---|---|
| Message-ID | <[email protected]> |
On 30/05/18 11:19, Dan Bloomquist wrote:
> Roeber, Steffen wrote:
>>
>> Hi,
>>
>> I want to parse something like "a=1;b=2;{c=3;d=4;}e=5;f=6;". My
>> problem is how to handle the block within the '{}' chars. The values
>> within the block shall be parsed (but not propagated to attribute of
>> r1) if ignoreBlock is true.
>>
>> usingnamespaceboost::spirit;
>> usingnamespacestd;
>> boolignoreBlock =true;
>> qi::rule<std::string::iterator,vector<pair<string,int>>()>r1;
>> qi::rule<std::string::iterator,pair<string,int>()>r2;
>> qi::rule<std::string::iterator,vector<pair<string,int>>()>r3;
>> r1 =*(r2 |(qi::eps(phoenix::ref(ignoreBlock)==true)>>qi::omit[r3])|r3);
>> r2 =qi::as<string>()[+qi::alnum]>>'='>>qi::int_ >>';';
>> r3 ='{'>>*r2 >>'}';
>> strings ={"a=1;b=2;{c=3;d=4;}e=5;f=6;"};
>> vector<pair<string,int>>v;
>> phrase_parse(s.begin(),s.end(),r1, boost::spirit::ascii::space,v);
>
> Hi Steffen, All,
> So I thought, why not just use x3 and wrote:
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> #include <vector>
> #include <boost/spirit/home/x3.hpp>
> #include <boost/fusion/adapted/std_pair.hpp>
>
> int main()
> {
> using namespace boost::spirit::x3;
> std::vector<std::pair<std::string, int>> v;
>
> auto const item_parser = *alnum >> '=' >> int_ >> ';'; //r2
> auto const set_parser = *(item_parser | omit['{' >> *item_parser >>
> '}']);
>
> std::string s( "a=1;b=2;{c=3;d=4;}e=5;f=6;" );
> auto b = s.begin();
> phrase_parse(b, s.end(), set_parser, space, v);
>
> return 0;
> }
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can have a look at Compound Attribute Rules [1] and find that in
(a | b) a: A, b: Unused --> (a | b): optional<A>
so you will always end up with an inferred attribute. Therefore I
suggest that you alter the grammar slightly to
*item_parser % x3::omit['{' >> *(x3::char_ - '}') >> '}']
that is a list of item_parsers, separated by brace groups. Since you
omit stuff inside the brace group anyway I took the liberty to make this
more general and just accept anything between braces (it should be easy
to go back). A full example can be found below.
[1]
https://www.boost.org/doc/libs/develop/libs/spirit/doc/x3/html/spirit_x3/quick_reference/compound_attribute_rules.html
#include <iostream>
#include <vector>
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
int main()
{
namespace x3 = boost::spirit::x3;
std::vector<std::pair<std::string, int>> v;
auto const item_parser = *x3::alnum >> '=' >> x3::int_ >> ';'; //r2
auto const set_parser = *item_parser % x3::omit['{' >> *(x3::char_
- '}') >> '}'] ;
std::string s( "a=1;b=2;{c=3;d=4;}e=5;f=6;" );
auto b = s.begin();
phrase_parse(b, s.end(), set_parser, x3::space, v);
for (auto const &p : v) {
std::cout << p.first << ' ' << p.second << '\n';
}
}
Output:
a 1
b 2
e 5
f 6
>
> Steffen, please note the inclusion of 'std_pair.hpp'. x3 needs it and I
> think qi does too from your error. I didn't try to qi build, so I don't
> know for sure.
>
> But my solution does not work! tracing I see 'omit' causes an unused
> attribute but an initialized pair makes its way back to the container
> move. My logic is most likely flawed or you just can't 'omit' as an
> alternative inside the kleene operator. But I don't know. My output was:
>
> a 1
> b 2
> 0 << from "",0 initialized pair
> e 5
> f 6
>
>
> Best, Dan.
>
>
> ------------------------------------------------------------------------------
>
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> Spirit-general mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/spirit-general
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Spirit-general mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/spirit-general