/*=============================================================================
    Spirit v1.6.0
    Copyright (c) 1998-2003 Joel de Guzman
    Copyright (c) 2003 Martin Wille
    http://spirit.sourceforge.net/

    Permission to copy, use, modify, sell and distribute this software is
    granted provided this copyright notice appears in all copies. This
    software is provided "as is" without express or implied warranty, and
    with no claim as to its suitability for any purpose.
=============================================================================*/
#if !defined(BOOST_SPIRIT_PRIMITIVES_HPP)
#define BOOST_SPIRIT_PRIMITIVES_HPP

#if !defined(BOOST_REF_HPP_INCLUDED)
#include "boost/ref.hpp"
#endif

#if !defined(BOOST_SPIRIT_ASSERT_HPP)
#include "boost/spirit/core/assert.hpp"
#endif

#if !defined(BOOST_SPIRIT_PARSER_HPP)
#include "boost/spirit/core/parser.hpp"
#endif

#if !defined(BOOST_SPIRIT_DIRECTIVES_IPP)
#include "boost/spirit/core/composite/impl/directives.ipp"
#endif

#if !defined(BOOST_SPIRIT_PRIMITIVES_IPP)
#include "boost/spirit/core/primitives/impl/primitives.ipp"
#endif

namespace boost { namespace spirit {

    ///////////////////////////////////////////////////////////////////////////
    //
    //  char_parser class
    //
    ///////////////////////////////////////////////////////////////////////////
    template <typename DerivedT>
    struct char_parser : public parser<DerivedT>
    {
        typedef DerivedT self_t;
        template <typename ScannerT>
        struct result {

            typedef typename match_result<
                ScannerT,
                typename ScannerT::value_t
            >::type type;
        };

        template <typename ScannerT>
        typename parser_result<self_t, ScannerT>::type
        parse(ScannerT const& scan) const
        {
            typedef typename parser_result<self_t, ScannerT>::type result_t;
            typedef typename ScannerT::value_t value_t;
            typedef typename ScannerT::iterator_t iterator_t;

            if (!scan.at_end())
            {
                value_t ch = *scan;
                if (this->derived().test(ch))
                {
                    iterator_t save(scan.first);
                    ++scan;
                    return scan.create_match(1, ch, save, scan.first);
                }
            }
            return scan.no_match();
        }
    };

    ///////////////////////////////////////////////////////////////////////////
    //
    //  negation of char_parsers
    //
    ///////////////////////////////////////////////////////////////////////////
    template <typename PositiveT>
    struct negated_char_parser
    : public char_parser<negated_char_parser<PositiveT> >
    {
        typedef negated_char_parser<PositiveT> self_t;
        typedef PositiveT positive_t;

        negated_char_parser(positive_t const& p)
        : positive(p.derived()) {}

        template <typename T>
        bool test(T ch) const
        { return !positive.test(ch); }

        positive_t const positive;
    };

    template <typename ParserT>
    inline negated_char_parser<ParserT>
    operator~(char_parser<ParserT> const& p)
    {
        return negated_char_parser<ParserT>(p.derived());
    }

    template <typename ParserT>
    inline ParserT
    operator~(negated_char_parser<ParserT> const& n)
    {
        return n.positive;
    }

    ///////////////////////////////////////////////////////////////////////////
    //
    //  chlit class
    //
    ///////////////////////////////////////////////////////////////////////////
    template <typename CharT = char>
    struct chlit : public char_parser<chlit<CharT> >
    {
        chlit(CharT ch_)
        : ch(ch_) {}

        template <typename T>
        bool test(T ch_) const
        { return ch_ == ch; }

        CharT   ch;
    };

    template <typename CharT>
    inline chlit<CharT>
    ch_p(CharT ch)
    { return chlit<CharT>(ch); }

    ///////////////////////////////////////////////////////////////////////////
    //
    //  range class
    //
    ///////////////////////////////////////////////////////////////////////////
    template <typename CharT = char>
    struct range : public char_parser<range<CharT> >
    {
        range(CharT first_, CharT last_)
        : first(first_), last(last_)
        {
            BOOST_SPIRIT_ASSERT(!(last < first));
        }

        template <typename T>
        bool test(T ch) const
        { return !(CharT(ch) < first) && !(last < CharT(ch)); }

        CharT   first;
        CharT   last;
    };

    template <typename CharT>
    inline range<CharT>
    range_p(CharT first, CharT last)
    { return range<CharT>(first, last); }

    ///////////////////////////////////////////////////////////////////////////
    //
    //  chseq class
    //
    ///////////////////////////////////////////////////////////////////////////
    template <typename IteratorT = char const*>
    class chseq : public parser<chseq<IteratorT> >
    {
    public:

        typedef chseq<IteratorT> self_t;

        chseq(IteratorT first_, IteratorT last_)
        : first(first_), last(last_) {}

        chseq(IteratorT first_)
        : first(first_), last(impl::get_last(first_)) {}

        template <typename ScannerT>
        typename parser_result<self_t, ScannerT>::type
        parse(ScannerT const& scan) const
        {
            typedef typename boost::unwrap_reference<IteratorT>::type striter_t;
            typedef typename parser_result<self_t, ScannerT>::type result_t;
            return impl::string_parser_parse<result_t>(
                striter_t(first),
                striter_t(last),
                scan);
        }

    private:

        IteratorT first;
        IteratorT last;
    };

    template <typename CharT>
    inline chseq<CharT const*>
    chseq_p(CharT const* str)
    { return chseq<CharT const*>(str); }

    template <typename IteratorT>
    inline chseq<IteratorT>
    chseq_p(IteratorT first, IteratorT last)
    { return chseq<IteratorT>(first, last); }

    ///////////////////////////////////////////////////////////////////////////
    //
    //  strlit class
    //
    ///////////////////////////////////////////////////////////////////////////
    template <typename IteratorT = char const*>
    class strlit : public parser<strlit<IteratorT> >
    {
    public:

        typedef strlit<IteratorT> self_t;

        strlit(IteratorT first, IteratorT last)
        : seq(first, last) {}

        strlit(IteratorT first)
        : seq(first) {}

        template <typename ScannerT>
        typename parser_result<self_t, ScannerT>::type
        parse(ScannerT const& scan) const
        {
            typedef typename parser_result<self_t, ScannerT>::type result_t;
            return impl::contiguous_parser_parse<result_t>
                (seq, scan, scan);
        }

    private:

        chseq<IteratorT> seq;
    };

    template <typename CharT>
    inline strlit<CharT const*>
    str_p(CharT const* str)
    { return strlit<CharT const*>(str); }

    template <typename IteratorT>
    inline strlit<IteratorT>
    str_p(IteratorT first, IteratorT last)
    { return strlit<IteratorT>(first, last); }

    ///////////////////////////////////////////////////////////////////////////
    //
    //  nothing_parser class
    //
    ///////////////////////////////////////////////////////////////////////////
    struct nothing_parser : public parser<nothing_parser>
    {
        typedef nothing_parser self_t;

        nothing_parser() {}

        template <typename ScannerT>
        typename parser_result<self_t, ScannerT>::type
        parse(ScannerT const& scan) const
        { return scan.no_match(); }
    };

    nothing_parser const nothing_p = nothing_parser();

    ///////////////////////////////////////////////////////////////////////////
    //
    //  anychar_parser class
    //
    ///////////////////////////////////////////////////////////////////////////
    struct anychar_parser : public char_parser<anychar_parser>
    {
        typedef anychar_parser self_t;

        anychar_parser() {}

        template <typename CharT>
        bool test(CharT) const
        { return true; }
    };

    anychar_parser const anychar_p = anychar_parser();

    ///////////////////////////////////////////////////////////////////////////
    //
    //  alnum_parser class
    //
    ///////////////////////////////////////////////////////////////////////////
    struct alnum_parser : public char_parser<alnum_parser>
    {
        typedef alnum_parser self_t;

        alnum_parser() {}

        template <typename CharT>
        bool test(CharT ch) const
        { return impl::isalnum_(ch); }
    };

    alnum_parser const alnum_p = alnum_parser();

    ///////////////////////////////////////////////////////////////////////////
    //
    //  alpha_parser class
    //
    ///////////////////////////////////////////////////////////////////////////
    struct alpha_parser : public char_parser<alpha_parser>
    {
        typedef alpha_parser self_t;

        alpha_parser() {}

        template <typename CharT>
        bool test(CharT ch) const
        { return impl::isalpha_(ch); }
    };

    alpha_parser const alpha_p = alpha_parser();

    ///////////////////////////////////////////////////////////////////////////
    //
    //  cntrl_parser class
    //
    ///////////////////////////////////////////////////////////////////////////
    struct cntrl_parser : public char_parser<cntrl_parser>
    {
        typedef cntrl_parser self_t;

        cntrl_parser() {}

        template <typename CharT>
        bool test(CharT ch) const
        { return impl::iscntrl_(ch); }
    };

    cntrl_parser const cntrl_p = cntrl_parser();

    ///////////////////////////////////////////////////////////////////////////
    //
    //  digit_parser class
    //
    ///////////////////////////////////////////////////////////////////////////
    struct digit_parser : public char_parser<digit_parser>
    {
        typedef digit_parser self_t;

        digit_parser() {}

        template <typename CharT>
        bool test(CharT ch) const
        { return impl::isdigit_(ch); }
    };

    digit_parser const digit_p = digit_parser();

    ///////////////////////////////////////////////////////////////////////////
    //
    //  graph_parser class
    //
    ///////////////////////////////////////////////////////////////////////////
    struct graph_parser : public char_parser<graph_parser>
    {
        typedef graph_parser self_t;

        graph_parser() {}

        template <typename CharT>
        bool test(CharT ch) const
        { return impl::isgraph_(ch); }
    };

    graph_parser const graph_p = graph_parser();

    ///////////////////////////////////////////////////////////////////////////
    //
    //  lower_parser class
    //
    ///////////////////////////////////////////////////////////////////////////
    struct lower_parser : public char_parser<lower_parser>
    {
        typedef lower_parser self_t;

        lower_parser() {}

        template <typename CharT>
        bool test(CharT ch) const
        { return impl::islower_(ch); }
    };

    lower_parser const lower_p = lower_parser();

    ///////////////////////////////////////////////////////////////////////////
    //
    //  print_parser class
    //
    ///////////////////////////////////////////////////////////////////////////
    struct print_parser : public char_parser<print_parser>
    {
        typedef print_parser self_t;

        print_parser() {}

        template <typename CharT>
        bool test(CharT ch) const
        { return impl::isprint_(ch); }
    };

    print_parser const print_p = print_parser();

    ///////////////////////////////////////////////////////////////////////////
    //
    //  punct_parser class
    //
    ///////////////////////////////////////////////////////////////////////////
    struct punct_parser : public char_parser<punct_parser>
    {
        typedef punct_parser self_t;

        punct_parser() {}

        template <typename CharT>
        bool test(CharT ch) const
        { return impl::ispunct_(ch); }
    };

    punct_parser const punct_p = punct_parser();

    ///////////////////////////////////////////////////////////////////////////
    //
    //  blank_parser class
    //
    ///////////////////////////////////////////////////////////////////////////
    struct blank_parser : public char_parser<blank_parser>
    {
        typedef blank_parser self_t;

        blank_parser() {}

        template <typename CharT>
        bool test(CharT ch) const
        { return ch == ' ' || ch == '\t'; }
        // some systems have isblank(), but some don't, so just do it manually.
    };

    //////////////////////////////////
    blank_parser const blank_p = blank_parser();

    ///////////////////////////////////////////////////////////////////////////
    //
    //  space_parser class
    //
    ///////////////////////////////////////////////////////////////////////////
    struct space_parser : public char_parser<space_parser>
    {
        typedef space_parser self_t;

        space_parser() {}

        template <typename CharT>
        bool test(CharT ch) const
        { return impl::isspace_(ch); }
    };

    space_parser const space_p = space_parser();

    ///////////////////////////////////////////////////////////////////////////
    //
    //  upper_parser class
    //
    ///////////////////////////////////////////////////////////////////////////
    struct upper_parser : public char_parser<upper_parser>
    {
        typedef upper_parser self_t;

        upper_parser() {}

        template <typename CharT>
        bool test(CharT ch) const
        { return impl::isupper_(ch); }
    };

    upper_parser const upper_p = upper_parser();

    ///////////////////////////////////////////////////////////////////////////
    //
    //  xdigit_parser class
    //
    ///////////////////////////////////////////////////////////////////////////
    struct xdigit_parser : public char_parser<xdigit_parser>
    {
        typedef xdigit_parser self_t;

        xdigit_parser() {}

        template <typename CharT>
        bool test(CharT ch) const
        { return impl::isxdigit_(ch); }
    };

    xdigit_parser const xdigit_p = xdigit_parser();

    ///////////////////////////////////////////////////////////////////////////
    //
    //  eol_parser class (contributed by Martin Wille)
    //
    ///////////////////////////////////////////////////////////////////////////
    struct eol_parser : public parser<eol_parser>
    {
        typedef eol_parser self_t;

        eol_parser() {}

        template <typename ScannerT>
        typename parser_result<self_t, ScannerT>::type
        parse(ScannerT const& scan) const
        {
            typename ScannerT::iterator_t save = scan.first;
            int len = 0;

            if (!scan.at_end() && *scan == '\r')    // CR
            {
                ++scan;
                ++len;
            }

            if (!scan.at_end() && *scan == '\n')    // LF
            {
                ++scan;
                ++len;
            }

            if (len)
                return scan.create_match(len, nil_t(), save, scan.first);
            return scan.no_match();
        }
    };

    eol_parser const eol_p = eol_parser();

    ///////////////////////////////////////////////////////////////////////////
    //
    //  end_parser class (suggested by Markus Schöpflin)
    //
    ///////////////////////////////////////////////////////////////////////////
    struct end_parser : public parser<end_parser>
    {
        typedef end_parser self_t;

        end_parser() {}

        template <typename ScannerT>
        typename parser_result<self_t, ScannerT>::type
        parse(ScannerT const& scan) const
        {
            if (scan.at_end())
                return scan.empty_match();
            return scan.no_match();
        }
    };

    end_parser const end_p = end_parser();

    ///////////////////////////////////////////////////////////////////////////
    //
    //  the pizza_p parser :-)
    //
    ///////////////////////////////////////////////////////////////////////////
    inline strlit<char const*> const
    pizza_p(char const* your_favorite_pizza)
    { return your_favorite_pizza; }

}} // namespace boost::spirit

#endif
