Boost logo

Boost Users :

Subject: Re: [Boost-users] boost-spirit: need help with simple parser
From: Allan Nielsen (a_at_[hidden])
Date: 2012-07-03 08:02:14


Hi,

Sorry for not providing the simplest possible code to reproduce my
problem, but I'm still new to spirit, I think I will miss some details
in the conversion.

I tried add the inclusion you suggested, but it did not help. In the
mean while, I found this page:
http://boost-spirit.com/home/2010/01/19/how-to-access-attributes-from-semantic-actions/
which is a very good match on what I would like to do.

The only problem is that I can not make it work...

Here is my second attempt (simper that the first, but not as simple as
you suggested... sorry)

#include <string>
#include <string.h>
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>

struct Ipv4 { union { uint32_t as_int; uint8_t as_char[4]; } raw; };

Ipv4 make_ipv4(uint8_t i1, uint8_t i2, uint8_t i3, uint8_t i4) {
    Ipv4 ip;
    ip.raw.as_char[0] = i1; ip.raw.as_char[1] = i2;
    ip.raw.as_char[2] = i3; ip.raw.as_char[3] = i4;
    return ip;
}

namespace qi = boost::spirit::qi;
qi::uint_parser<uint8_t, 10, 1, 3> octet;

struct Ipv4Address : qi::grammar<const char *, Ipv4()> {
    Ipv4Address() : Ipv4Address::base_type(start) {
        start = ( octet >> qi::lit('.') >> octet >> qi::lit('.') >>
                  octet >> qi::lit('.') >> octet
                ) [
                    //qi::_val = make_ipv4(1, 2, 3, 4) // working
                    qi::_val = make_ipv4(qi::_1, qi::_2, qi::_3,
qi::_4) // compile error
                ]
        ;
    }
    qi::rule<const char *, Ipv4()> start;
} ipv4_address;

int main() {
    Ipv4 ip;
    const char * s = "1.2.3.4";
    bool r = qi::parse(s, s+strlen(s), ipv4_address, ip);
    std::cout << r << " " << (int)ip.raw.as_char[0] << "." <<
                             (int)ip.raw.as_char[1] << "." <<
                             (int)ip.raw.as_char[2] << "." <<
                             (int)ip.raw.as_char[3] << std::endl;
}

When compiling this I get the following compile error:

/tmp/ip.cxx: In constructor 'Ipv4Address::Ipv4Address()':
/tmp/ip.cxx:26:72: error: cannot convert 'const _1_type {aka const
boost::phoenix::actor<boost::spirit::argument<0> >}' to 'uint8_t {aka
unsigned char}' for argument '1' to 'Ipv4 make_ipv4(uint8_t, uint8_t,
uint8_t, uint8_t)'

Any hints?

Best regards
Allan W. Nielsen

On Tue, Jul 3, 2012 at 1:10 PM, Igor R <boost.lists_at_[hidden]> wrote:
>> or even simpler:
>> boost::tuple<uint8_t, uint8_t, uint8_t, uint8_t> v;
>> bool r = qi::parse(s.begin(), s.end(), octet >> '.' >> octet >> '.'
>>>> octet >> '.' >> octet, v);
>>
>> while the following works correctly:
>> boost::fusion::vector<uint8_t, uint8_t, uint8_t, uint8_t> v;
>> bool r = qi::parse(s.begin(), s.end(), octet >> '.' >> octet >> '.'
>>>> octet >> '.' >> octet, v);
>>
>> So, the attribute gets converted to boost::tuple is some strange way...
>
>
> Well, finally got it.
> You have to #include <boost/fusion/include/boost_tuple.hpp> to get
> boost::tuple adapted correctly.
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net