|
Boost : |
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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk