$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: [boost] [proto] [ was Re: [spirit2] Trivial parser crashes ]
From: Joel de Guzman (joel_at_[hidden])
Date: 2008-11-18 05:12:36
Joel de Guzman wrote:
> Joel de Guzman wrote:
>> sm4 wrote:
>>> Oops - seems formatting got in the way.
>>>
>>> Hope this is better:
>>
>> Ooops, I missed your reply. Its better to post spirit
>> related questions to spirit's mailing list. I'm re-posting
>> this there.
> 
> Ok, this looks like a bug in handling aliases of the form:
> 
>     r1 %= r2;
> 
> where r1 and r2 are rules with the same type. A quick
> workaround is to copy the rhs rule:
> 
>     r1 %= r2.copy();
Eric,
It seems to be a problem with Spirit2's usage of proto extends.
Here's what's happening:
1) Rule uses proto::extends
2) Rule implements operator %=
On expressions:
     r %= some-expression;
The rule's operator%= kicks in. However, on expressions:
     r %= r2; // r and r2 has the same type
Then proto %= kicks in leaving it as a no-op. Nothing happens.
Hence, the rhs is never "auto-assigned" to the lhs.
I'm not sure how to deal with this. Do you have a hint?
I place the original test code here. Tracing the code, the
first %= works as expected while the second and third becomes
no-ops calling proto operator %=.
 > 
-----------------------------------------------------------------------------------------
 > #include <boost/config/warning_disable.hpp>
 > #include <boost/spirit/include/qi.hpp>
 > #include <boost/spirit/include/phoenix_core.hpp>
 > #include <boost/spirit/include/phoenix_operator.hpp>
 > #include <boost/spirit/include/phoenix_fusion.hpp>
 > #include <boost/fusion/include/adapt_struct.hpp>
 > #include <boost/fusion/include/adapt_struct.hpp>
 >
 > #include <iostream>
 > #include <string>
 >
 > using namespace boost::spirit;
 > using namespace boost::spirit::qi;
 > using namespace boost::spirit::ascii;
 > using namespace boost::spirit::arg_names;
 >
 > namespace phoenix = boost::phoenix;
 >
 > using phoenix::at_c;
 >
 > struct key_val
 > {
 >     std::string key;
 >     std::string value;
 > };
 >
 > BOOST_FUSION_ADAPT_STRUCT(
 >     key_val,
 >     (std::string, key)
 >     (std::string, value)
 > )
 >
 >
 > template <typename Iterator>
 > struct my_grammar : grammar<Iterator, key_val(), space_type>
 > {
 >     my_grammar() : my_grammar::base_type(start)
 >     {
 >         quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];
 >         key %= quoted_string;
 >         value %= quoted_string;
 >
 >         start =
 >                 key           [at_c<0>(_val) = _1]
 >              >> ':'
 >              >> value         [at_c<1>(_val) = _1]
 >              ;
 >     }
 >
 >     rule<Iterator, std::string(), space_type> key;
 >     rule<Iterator, std::string(), space_type> quoted_string;
 >     rule<Iterator, std::string(), space_type> value;
 >
 >     rule<Iterator, key_val(), space_type> start;
 >
 > };
 >
 > int main()
 > {
 >     typedef std::string::const_iterator citerator;
 >     std::string str = "\"x\": \"25\" ";
 >
 >     citerator iter = str.begin();
 >     citerator end = str.end();
 >
 >     my_grammar<citerator> my_parser;
 >     key_val kv;
 >     phrase_parse(iter, end, my_parser, kv, space); // ASSERTs
 >
 >     return 0;
 > }
 > 
-----------------------------------------------------------------------------------------
Regards,
-- Joel de Guzman http://www.boostpro.com http://spirit.sf.net