2

I have the following code in Classic Spirit:

/// _BasicRules.h
template <typename scanT> class _BasicRules {
    public:
        _BasicRules() {
            // ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
            ALPHA = range_p(0x41, 0x5A) | range_p(0x61, 0x7A);
            ...
        }
    protected:
        boost::spirit::rule<scanT> ALPHA;
        ...
};

// CommonRules.h
template <typename scanT> class _CommonRules : public _BasicRules<scanT> {...};

// _UriRules.h
template <typename scanT> class _UriRules : public _CommonRules<scanT> {...};

// _HeaderRules.h
template <class scanT> class _HeaderRules : public _UriRules<scanT> {...};

// _SipRules.h
template <typename scanT> class SipGrammar::definition : public _HeaderRules<scanT> {
public:
    definition(SipGrammar const& self) {
        SIP_message = Request | Response; 
        Request = Request_Line >> *(message_header) >> CRLF >> !message_body;
        ...
    }
    const rule<scanT> & start() const
    {
        return SIP_message;
    }
  private:
    boost::spirit::rule<scanT> SIP_message;
    using _BasicRules<scanT>::DIGIT;
    using _CommonRules<scanT>::token;
    ...
};

I am just converting RFC3261 based SIP Message parser from Spirirt Classic to new Spirit 2.5.2. I have splitted whole grammar into multiple inherited files as grammar is really huge.

I am writing this code;

....
template <typename Iterator> struct _HeaderRules:grammar<Iterator>, _UriRules<Iterator> {...}
template <typename Iterator> struct SipGrammar:grammar<Iterator>, _HeaderRules<Iterator> {
    SipGrammar():SipGrammar::base_type(SIP_Message){...}
    ...
};

This does not work. Would you suggest a source for hierarchically splitting grammar in Spirit 2.5.2.

  • 4
    You might want to expand on "this does not work". – Bart Sep 07 '13 at 19:59
  • 2
    Also, [identifiers beginning with an underscore and an uppercase letter are reserved in any scope](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier). Your program's behaviour is technically undefined – sehe Sep 07 '13 at 20:23

1 Answers1

3

Inheritance isn't a logical choice here, by any means (a SipGrammar is not Liskov-Substitutable for a HeaderRules in any sense).

The usual way to go about this, would be aggregation:

template <typename Iterator> struct SipGrammar : grammar<Iterator>
{
    SipGrammar() : SipGrammar::base_type(SIP_Message)
    {
        ...
    }

  private:

     HeaderRule<Iterator> _headerRules;
    ...
};

The compiler examples in the Boost Spirit source tree contain several examples of how this can be done while splitting hpp/cpp files at the same time, indeed to reduce compilation times:

sehe
  • 374,641
  • 47
  • 450
  • 633
  • The compiler example does split the grammar in different compilation units (see for instance calc7 folder, expression classes). It is just a little bit hard to follow, because it is large. – Gab Dec 23 '14 at 21:02