Suggestions on how to use boost spirit to parse ipv6 address
===

I am looking for some guidance on the best way to use boost spirit to parse an ipv6 address using spirit::qi and eventually generate the ipv6 address using qi::karma.

The grammar would be based on the following rfc:
http://tools.ietf.org/html/draft-ietf-sip-ipv6-abnf-fix-05#section-3.1

It seems that there is a trend to not use semantic actions in the grammar.
 
So my question is, if I don't use semantic actions, what is the best way to get the ipv6 address out of the parser which would later let me use spirit::karma to regenerate the address?


Here is the code I have so far to parse the ipv6 address. At the moment it just uses the auto generated attribute of the rule, which is a vector. Unfortunately this does not store enough information to recreate the ipv6 address from this vector as it has lost all information as to where the double colon appeared in the vector of uint16_ts.

Does anyone have any guidelines as to how to handle the parsing of the ipv6 address which would hopefully also make the generation using spirit::karma easy?

Do I attach semantic actions and pass in some struct that can have an index set telling where in the sequence of uint16_ts the colon appears? Although this seems to break the rule of trying not to use semantic actions if possible.



    namespace sdp
    {    
        typedef uint16_t                  IPV6AddrElem;
        typedef std::vector<IPV6AddrElem> IPV6AddrElems;
        
        /*
         * http://tools.ietf.org/html/draft-ietf-sip-ipv6-abnf-fix-05
         *
         * IPv6address   =                             6( h16 ":" ) ls32
         *                /                       "::" 5( h16 ":" ) ls32
         *                / [               h16 ] "::" 4( h16 ":" ) ls32
         *                / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
         *                / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
         *                / [ *3( h16 ":" ) h16 ] "::"    h16 ":"   ls32
         *                / [ *4( h16 ":" ) h16 ] "::"              ls32
         *                / [ *5( h16 ":" ) h16 ] "::"              h16
         *                / [ *6( h16 ":" ) h16 ] "::"
         *
         * h16           = 1*4HEXDIG
         * ls32          = ( h16 ":" h16 ) / IPv4address
         *
         */
        template<typename Iter>
        struct IPV6Grammar1 : boost::spirit::qi::grammar<Iter, IPV6AddrElems()>
        {             
            IPV6Grammar1() : IPV6Grammar1::base_type(ipv6address, "IPV6Grammar")
            {  
                namespace qi = boost::spirit::qi;
                using qi::repeat;
                
                ipv6address
                %=
                (                                                 repeat(6)[h16 >> ':'] >> ls32 
                 |                                        "::" >> repeat(5)[h16 >> ':'] >> ls32 
                 |  -(                            h16) >> "::" >> repeat(4)[h16 >> ':'] >> ls32  
                 |  -(repeat(0, 1)[h16 >> ':'] >> h16) >> "::" >> repeat(3)[h16 >> ':'] >> ls32 
                 |  -(repeat(0, 2)[h16 >> ':'] >> h16) >> "::" >> repeat(2)[h16 >> ':'] >> ls32 
                 |  -(repeat(0, 3)[h16 >> ':'] >> h16) >> "::" >>           h16 >> ':'  >> ls32 
                 |  -(repeat(0, 4)[h16 >> ':'] >> h16) >> "::"                          >> ls32 
                 |  -(repeat(0, 5)[h16 >> ':'] >> h16) >> "::" >>           h16                 
                 |  -(repeat(0, 6)[h16 >> ':'] >> h16) >> "::"                                  
                 )
                ;
                
                h16 
                =   hexParser
                ;
                
                ls32
                =   h16 >> ':' >> h16
                //|   ipv4address
                ;
                
                BOOST_SPIRIT_DEBUG_NODE(ipv6address);
                BOOST_SPIRIT_DEBUG_NODE(h16);
                BOOST_SPIRIT_DEBUG_NODE(ls32);
            }
            
        private: // data
            
            boost::spirit::qi::rule<Iter, IPV6AddrElems()>         ipv6address;
            boost::spirit::qi::rule<Iter, IPV6AddrElem()>          h16;
            boost::spirit::qi::rule<Iter, IPV6AddrElems()>         ls32;
            boost::spirit::qi::uint_parser<IPV6AddrElem, 16, 1, 4> hexParser;
            //IPV4Grammar<Iter>                                     ipv4address;
        };
    }