/*=============================================================================

    Copyright (c) 1998-2003 Joel de Guzman

    http://spirit.sourceforge.net/



    Use, modification and distribution is subject to the Boost Software

    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at

    http://www.boost.org/LICENSE_1_0.txt)

=============================================================================*/

#if !defined(BOOST_SPIRIT_SKIPPER_HPP)

#define BOOST_SPIRIT_SKIPPER_HPP



///////////////////////////////////////////////////////////////////////////////

#include <cctype>



#include <boost/spirit/core/scanner/scanner.hpp>

#include <boost/spirit/core/primitives/impl/primitives.ipp>



#include <boost/spirit/core/scanner/skipper_fwd.hpp>



namespace boost { namespace spirit {



    ///////////////////////////////////////////////////////////////////////////

    //

    //  skipper_iteration_policy class

    //

    ///////////////////////////////////////////////////////////////////////////

    template <typename BaseT>

    struct skipper_iteration_policy : public BaseT

    {

        typedef BaseT base_t;

    

        skipper_iteration_policy()

        : BaseT() {}

    

        template <typename PolicyT>

        skipper_iteration_policy(PolicyT const& other)

        : BaseT(other) {}

    

        template <typename ScannerT>

        void

        advance(ScannerT const& scan) const

        {

            BaseT::advance(scan);

            scan.skip(scan);

        }

    

        template <typename ScannerT>

        bool

        at_end(ScannerT const& scan) const

        {

            scan.skip(scan);

            return BaseT::at_end(scan);

        }

    

        template <typename ScannerT>

        void

        skip(ScannerT const& scan) const

        {

            while (!BaseT::at_end(scan) && impl::isspace_(BaseT::get(scan)))

                BaseT::advance(scan);

        }

    };

    

    ///////////////////////////////////////////////////////////////////////////

    //

    //  no_skipper_iteration_policy class

    //

    ///////////////////////////////////////////////////////////////////////////

    template <typename BaseT>

    struct no_skipper_iteration_policy : public BaseT

    {

        typedef BaseT base_t;



        no_skipper_iteration_policy()

        : BaseT() {}



        template <typename PolicyT>

        no_skipper_iteration_policy(PolicyT const& other)

        : BaseT(other) {}



        template <typename ScannerT>

        void

        skip(ScannerT const& /*scan*/) const {}

    };



    ///////////////////////////////////////////////////////////////////////////

    //

    //  skip_parser_iteration_policy class

    //

    ///////////////////////////////////////////////////////////////////////////

    namespace impl

    {

        template <typename ST, typename ScannerT, typename BaseT>

        void

        skipper_skip(

            ST const& s,

            ScannerT const& scan,

            skipper_iteration_policy<BaseT> const&);



        template <typename ST, typename ScannerT, typename BaseT>

        void

        skipper_skip(

            ST const& s,

            ScannerT const& scan,

            no_skipper_iteration_policy<BaseT> const&);



        template <typename ST, typename ScannerT>

        void

        skipper_skip(

            ST const& s,

            ScannerT const& scan,

            iteration_policy const&);

    }



    template <typename ParserT, typename BaseT>

    class skip_parser_iteration_policy : public skipper_iteration_policy<BaseT>

    {

    public:

    

        typedef skipper_iteration_policy<BaseT> base_t;

    

        skip_parser_iteration_policy(

            ParserT const& skip_parser,

            base_t const& base = base_t())

        : base_t(base), subject(skip_parser) {}

    

        template <typename PolicyT>

        skip_parser_iteration_policy(PolicyT const& other)

        : base_t(other), subject(other.skipper()) {}

    

        template <typename ScannerT>

        void

        skip(ScannerT const& scan) const

        {

            impl::skipper_skip(subject, scan, scan);

        }

    

        ParserT const&

        skipper() const

        { 

            return subject; 

        }

    

    private:

    

        ParserT const& subject;

    };

    

    ///////////////////////////////////////////////////////////////////////////////

    //

    //  Free parse functions using the skippers

    //

    ///////////////////////////////////////////////////////////////////////////////

    template <typename IteratorT, typename ParserT, typename SkipT>

    parse_info<IteratorT>

    parse(

        IteratorT const&        first,

        IteratorT const&        last,

        parser<ParserT> const&  p,

        parser<SkipT> const&    skip);

    

    ///////////////////////////////////////////////////////////////////////////////

    //

    //  Parse function for null terminated strings using the skippers

    //

    ///////////////////////////////////////////////////////////////////////////////

    template <typename CharT, typename ParserT, typename SkipT>

    parse_info<CharT const*>

    parse(

        CharT const*            str,

        parser<ParserT> const&  p,

        parser<SkipT> const&    skip);

    

    ///////////////////////////////////////////////////////////////////////////////

    //

    //  phrase_scanner_t and wide_phrase_scanner_t

    //

    //      The most common scanners. Use these typedefs when you need

    //      a scanner that skips white spaces.

    //

    ///////////////////////////////////////////////////////////////////////////////

    typedef skipper_iteration_policy<>                  iter_policy_t;

    typedef scanner_policies<iter_policy_t>             scanner_policies_t;

    typedef scanner<char const*, scanner_policies_t>    phrase_scanner_t;

    typedef scanner<wchar_t const*, scanner_policies_t> wide_phrase_scanner_t;

    

    ///////////////////////////////////////////////////////////////////////////////

}} // namespace boost::spirit



#include <boost/spirit/core/scanner/impl/skipper.ipp>

#endif



