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