#include <iostream>
#include <boost/spirit/core.hpp>

using namespace boost::spirit;

namespace boost { namespace spirit
{
    template <typename DerivedT>
    struct sub_grammar : parser<DerivedT>
    {
        typedef sub_grammar         self_t;
        typedef DerivedT const&     embed_t;

        template <typename ScannerT>
        struct result
        {
            typedef typename parser_result<
                typename DerivedT::start_t, ScannerT>::type
            type;
        };

        DerivedT const& derived() const
        { return *static_cast<DerivedT const*>(this); }

        template <typename ScannerT>
        typename parser_result<self_t, ScannerT>::type
        parse(ScannerT const& scan) const
        { return derived().start.parse(scan); }
    };
}}

#ifdef __MWERKS__
#define typeof __typeof__
#endif

///////////////////////////////////////////////////////////////////////////////
//  Client code
///////////////////////////////////////////////////////////////////////////////
#define CPP_COMMENT     ("//" >> *(anychar_p - '\n') >> '\n')
#define C_COMMENT       ("/*" >> *(anychar_p - "*/") >> "*/")
#define LINE            ("#line" >> *(anychar_p - '\n') >> '\n')
#define PRAGMA          ("#pragma" >> *(anychar_p - '\n') >> '\n')
#define C_SKIPPER       (space_p | CPP_COMMENT | C_COMMENT | LINE | PRAGMA)

typedef typeof(CPP_COMMENT) cpp_comment_t;
typedef typeof(C_COMMENT)   c_comment_t;
typedef typeof(LINE)        line_t;
typedef typeof(PRAGMA)      pragma_t;
typedef typeof(C_SKIPPER)   c_skipper_t;

struct skip_grammar : sub_grammar<skip_grammar>
{
    typedef c_skipper_t start_t;

    cpp_comment_t   cpp_comment;
    c_comment_t     c_comment;
    line_t          line;
    pragma_t        pragma;
    start_t         start;

    skip_grammar()
    : cpp_comment(CPP_COMMENT)
    , c_comment(C_COMMENT)
    , line(LINE)
    , pragma (PRAGMA)
    , start(C_SKIPPER)
    {}
};

int
main()
{
    skip_grammar g;

    bool success = parse(
        "/*this is a comment*/\n//this is a c++ comment\n\n",
        *g).full;
    assert(success);
    std::cout << "SUCCESS!!!\n";
    return 0;
}
