/*=============================================================================
    Copyright (c) 1998-2003 Joel de Guzman
    Copyright (c) 2003 Vaclav Vesely
    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_DISTINCT_HPP)
#define BOOST_SPIRIT_DISTINCT_HPP

#include <boost/spirit/core/parser.hpp>
#include <boost/spirit/core/primitives/primitives.hpp>
#include <boost/spirit/core/composite/operators.hpp>
#include <boost/spirit/core/composite/directives.hpp>
#include <boost/spirit/core/composite/epsilon.hpp>
#include <boost/spirit/core/non_terminal/rule.hpp>
#include <boost/spirit/utility/chset.hpp>

namespace boost {
    namespace spirit {
//-----------------------------------------------------------------------------
// distinct_parser class

template <typename CharT = char, typename TailT = chset<CharT> >
class distinct_parser
{
public:
    typedef
        contiguous<
            sequence<
                chseq<CharT const*>,
                negated_empty_match_parser<
                    TailT
                >
            >
        >
            result_t;

    distinct_parser()
    :   tail(chset<CharT>())
    {
    }

    explicit distinct_parser(parser<TailT> const & tail_)
    :   tail(tail_.derived())
    {
    }

    explicit distinct_parser(CharT const* letters)
    :   tail(chset_p(letters))
    {
    }

    result_t operator()(CharT const* str) const
    {
        return lexeme_d[chseq_p(str) >> ~epsilon_p(tail)];
    }

    TailT tail;
};

//-----------------------------------------------------------------------------
// distinct_directive class

template <typename CharT = char, typename TailT = chset<CharT> >
class distinct_directive
{
public:
    template<typename ParserT>
    struct result {
        typedef
            contiguous<
                sequence<
                    ParserT,
                    negated_empty_match_parser<
                        TailT
                    >
                >
            >
                type;
    };

    distinct_directive()
    :   tail(chset<CharT>())
    {
    }

    explicit distinct_directive(CharT const* letters)
    :   tail(chset_p(letters))
    {
    }

    explicit distinct_directive(parser<TailT> const & tail_)
    :   tail(tail_.derived())
    {
    }

    template<typename ParserT>
    typename result<typename as_parser<ParserT>::type>::type
        operator[](ParserT const &subject) const
    {
        return
            lexeme_d[as_parser<ParserT>::convert(subject) >> ~epsilon_p(tail)];
    }

    TailT tail;
};

//-----------------------------------------------------------------------------
// dynamic_distinct_parser class

template <typename ScannerT = scanner<> >
class dynamic_distinct_parser
{
public:
    typedef typename ScannerT::value_t char_t;

    typedef
        rule<
            typename no_actions_scanner<
                typename lexeme_scanner<ScannerT>::type
            >::type
        >
            tail_t;

    typedef
        contiguous<
            sequence<
                chseq<char_t const*>,
                negated_empty_match_parser<
                    tail_t
                >
            >
        >
            result_t;

    dynamic_distinct_parser()
    :   tail(nothing_p)
    {
    }

    template<typename ParserT>
    explicit dynamic_distinct_parser(parser<ParserT> const & tail_)
    :   tail(tail_.derived())
    {
    }

    explicit dynamic_distinct_parser(char_t const* letters)
    :   tail(chset_p(letters))
    {
    }

    result_t operator()(char_t const* str) const
    {
        return lexeme_d[chseq_p(str) >> ~epsilon_p(tail)];
    }

    tail_t tail;
};

//-----------------------------------------------------------------------------
// dynamic_distinct_directive class

template <typename ScannerT = scanner<> >
class dynamic_distinct_directive
{
public:
    typedef typename ScannerT::value_t char_t;

    typedef
        rule<
            typename no_actions_scanner<
                typename lexeme_scanner<ScannerT>::type
            >::type
        >
            tail_t;

    template<typename ParserT>
    struct result {
        typedef
            contiguous<
                sequence<
                    ParserT,
                    negated_empty_match_parser<
                        tail_t
                    >
                >
            >
                type;
    };

    dynamic_distinct_directive()
    :   tail(nothing_p)
    {
    }

    template<typename ParserT>
    explicit dynamic_distinct_directive(parser<ParserT> const & tail_)
    :   tail(tail_.derived())
    {
    }

    explicit dynamic_distinct_directive(char_t const* letters)
    :   tail(chset_p(letters))
    {
    }

    template<typename ParserT>
    typename result<typename as_parser<ParserT>::type>::type
        operator[](ParserT const &subject) const
    {
        return
            lexeme_d[as_parser<ParserT>::convert(subject) >> ~epsilon_p(tail)];
    }

    tail_t tail;
};

//-----------------------------------------------------------------------------
    } // namespace spirit
} // namespace boost

#endif // !defined(BOOST_SPIRIT_DISTINCT_HPP)
