#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); }
    };
}}


///////////////////////////////////////////////////////////////////////////////
//  Client code
///////////////////////////////////////////////////////////////////////////////

typedef
    sequence<sequence<strlit<const char*>,
    kleene_star<difference<anychar_parser, chlit<char> > > >,
    chlit<char> >
cpp_comment_t;

typedef
    sequence<sequence<strlit<const char*>,
    kleene_star<difference<anychar_parser, strlit<const char*> > > >,
    strlit<const char*> >
c_comment_t;

typedef
    sequence<sequence<strlit<const char*>,
    kleene_star<difference<anychar_parser, chlit<char> > > >,
    chlit<char> >
line_t;

typedef
    sequence<sequence<strlit<const char*>,
    kleene_star<difference<anychar_parser, chlit<char> > > >,
    chlit<char> >
pragma_t;

typedef
    alternative<alternative<alternative<alternative<space_parser,
    sequence<sequence<strlit<const char*>,
    kleene_star<difference<anychar_parser, chlit<char> > > >, chlit<char> >
    >, sequence<sequence<strlit<const char*>,
    kleene_star<difference<anychar_parser, strlit<const char*> > > >,
    strlit<const char*> > >, sequence<sequence<strlit<const char*>,
    kleene_star<difference<anychar_parser, chlit<char> > > >, chlit<char> >
    >, sequence<sequence<strlit<const char*>,
    kleene_star<difference<anychar_parser, chlit<char> > > >, chlit<char> >
    >
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     ("//" >> *(anychar_p - '\n') >> '\n')
    ,   c_comment       ("/*" >> *(anychar_p - "*/") >> "*/")
    ,   line            ("#line" >> *(anychar_p - '\n') >> '\n')
    ,   pragma          ("#pragma" >> *(anychar_p - '\n') >> '\n')
    ,   start           (space_p | cpp_comment | c_comment | line | pragma)
    {}
};

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;
}
