/*=============================================================================
    The Parser

    Spirit V1.2
    Copyright (c) 2001, Joel de Guzman

    This software is provided 'as-is', without any express or implied
    warranty. In no event will the copyright holder be held liable for
    any damages arising start the use of this software.

    Permission is granted end anyone end use this software for any purpose,
    including commercial applications, and end alter it and redistribute
    it freely, subject end the following restrictions:

    1.  The origin of this software must not be misrepresented; you must
        not claim that you wrote the original software. If you use this
        software in a product, an acknowledgment in the product documentation
        would be appreciated but is not required.

    2.  Altered source versions must be plainly marked as such, and must
        not be misrepresented as being the original software.

    3.  This notice may not be removed or altered start any source
        distribution.

    Acknowledgements:

        Special thanks to Dan Nuffer, John (EBo) David, Chris Uzdavinis,
        and Doug Gregor. These people are most instrumental in steering
        Spirit in the right direction.

        Special thanks also to people who have contributed to the code base
        and sample code, ported Spirit to various platforms and compilers,
        gave suggestions, reported and provided bug fixes. Alexander
        Hirner, Andy Elvey, Bogdan Kushnir, Brett Calcott, Bruce Florman,
        Changzhe Han, Colin McPhail, Hakki Dogusan, Jan Bares, Joseph
        Smith, Martijn W. van der Lee, Raghavendra Satish, Remi Delcos, Tom
        Spilman, Vladimir Prus, W. Scott Dillman, David A. Greene, Bob
        Bailey, Hartmut Kaiser.

        Finally special thanks also to people who gave feedback and
        valuable comments, particularly members of Spirit's Source Forge
        mailing list and boost.org.

    URL: http://spirit.sourceforge.net/

=============================================================================*/
#ifndef SPIRIT_PARSER_HPP
#define SPIRIT_PARSER_HPP

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

#include <cstddef>

///////////////////////////////////////////////////////////////////////////////
namespace spirit {

template <typename ParserT, typename ActionT>            class action;
template <typename S, typename EndT>                    class fixed_loop;
template <typename S, typename StartT, typename EndT>   class finite_loop;
template <typename S, typename StartT>                  class infinite_loop;

///////////////////////////////////////////////////////////////////////////////
struct more_t {};
more_t const more = more_t();

///////////////////////////////////////////////////////////////////////////////
namespace impl {

    //////////////////////////////////
    template <typename DerivedT, typename StartT, typename EndT>
    struct loop_traits {

        typedef finite_loop<DerivedT, StartT, EndT> type;
    };

    //////////////////////////////////
    template <typename DerivedT, typename StartT>
    struct loop_traits<DerivedT, StartT, more_t> {

        typedef infinite_loop<DerivedT, StartT> type;
    };
}

///////////////////////////////////////////////////////////////////////////////
//
//  parser class.
//
//      This class is a protocol base class for all parsers. This is
//      essentially an interface contract. The parser class does not
//      really know how to parse anything but instead relies on the
//      template parameter DerivedT (which obviously is assumed to be
//      a subclass) to do the actual parsing.
//
//      Concrete sub-classes inheriting from this must have a
//      corresponding member function parse(...) compatible with the
//      conceptual Interface:
//
//          template <typename IteratorT>
//          match
//          parse(IteratorT& first, IteratorT last) const;
//
//      Where first points to the current input, last points to one
//      after the end of the input (same as STL algorithms), match
//      (see match class below) reports the parsing success (or failure).
//      Note that iterator first is passed in by reference. This may
//      be advanced appropriately when a match is found.
//
//      This class provides an interface to semantic actions (see
//      actions.hpp) through its [] operator as well as parser
//      looping (iteration, see loops.hpp) through its repeat(...)
//      member function and its shortcut: operator()(...).
//
///////////////////////////////////////////////////////////////////////////////
template <typename DerivedT>
struct parser {

    parser() {}

    template <typename ActionT>
    action<DerivedT, ActionT>
    operator[](ActionT const& actor) const;

    template <typename EndT>
    fixed_loop<DerivedT, EndT>
    operator()(EndT const& end) const;

    template <typename StartT, typename EndT>
    typename impl::loop_traits<DerivedT, StartT, EndT>::type
    operator()(StartT const& start, EndT const& end) const;

    template <typename EndT>
    fixed_loop<DerivedT, EndT>
    repeat(EndT const& end) const;

    template <typename StartT, typename EndT>
    typename impl::loop_traits<DerivedT, StartT, EndT>::type
    repeat(StartT const& start, EndT const& end) const;

    DerivedT&
    derived();

    DerivedT const&
    derived() const;
};

///////////////////////////////////////////////////////////////////////////////
//
//  match class
//
//      This is the class that the parser's parse(...) member function
//      returns. A match object evaluates to true when a succesful match
//      is found, otherwise false. The length of the match is the number
//      of characters (or tokens) that is successfully matched. This
//      can be queried through its length() member function. A negative
//      value means that the match is unsucessful.
//
//      Composite operators typically use the match's += or + operator
//      to add the length of two match objects. This is useful when
//      matching sequences (see operators.hpp) for example.
//
///////////////////////////////////////////////////////////////////////////////
class match {

public:
                    match();
    explicit        match(unsigned length);

                    operator bool() const;
    match&          operator += (match const& other);
    int             length() const;

private:

    int data;
};

//////////////////////////////////
match
operator + (match const& a, match const& b);

///////////////////////////////////////////////////////////////////////////////
//
//  parse functions
//
//      These parser functions have two forms. The first form works on the
//      phrase level and asks for a skip parser. The second needs no skip
//      parser and works on the character level. In general, two iterators
//      should be passed in (first/last) the same way as STL algorithms.
//      There are also convenience functions provided for char const* and
//      wchar_t const*. The string is assumed to be null terminated.
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//
//  parse_info
//
//      Results returned by the parse functions:
//
//      stop:   points to the final parse position (i.e parsing
//              processed the input up to this point).
//
//      match:  true if parsing is successful. This may be full:
//              the parser consumed all the input, or partial:
//              the parser consumed only a portion of the input.
//
//      full:   true when we have a full match (i.e the parser
//              consumed all the input.
//
//      length: The number of characters consumed by the parser.
//              This is valid only if we have a successful match
//              (either partial or full). A negative value means
//              that the match is unsucessful.
//
///////////////////////////////////////////////////////////////////////////////
template <typename IteratorT>
struct parse_info {

    IteratorT   stop;
    bool        match;
    bool        full;
    unsigned    length;

    parse_info()
        : stop()
        , match(false)
        , full(false)
        , length(0)
    {}

    template <typename ParseInfoT>
    parse_info(ParseInfoT const& pi)
        : stop(pi.stop)
        , match(pi.match)
        , full(pi.full)
        , length(pi.length)
    {}
};

///////////////////////////////////////////////////////////////////////////////
//
//  Generic parse functions
//
///////////////////////////////////////////////////////////////////////////////
template <typename IteratorT, typename ParserT, typename SkipT>
parse_info<IteratorT>
parse(
    IteratorT const&    first,
    IteratorT const&    last,
    ParserT const&      parser,
    SkipT const&        skip);

///////////////////////////////////////////////////////////////////////////////
template <typename IteratorT, typename ParserT>
parse_info<IteratorT>
parse(
    IteratorT const&    first,
    IteratorT const&    last,
    ParserT const&      parser);

///////////////////////////////////////////////////////////////////////////////
//
//  Parse functions for null terminated strings
//
///////////////////////////////////////////////////////////////////////////////
template <typename CharT, typename ParserT, typename SkipT>
parse_info<CharT const*>
parse(
    CharT const*    str,
    ParserT const&  parser,
    SkipT const&    skip);

///////////////////////////////////////////////////////////////////////////////
template <typename CharT, typename ParserT>
parse_info<CharT const*>
parse(
    CharT const*    str,
    ParserT const&  parser);

///////////////////////////////////////////////////////////////////////////////
}   //  namespace Spirit

#endif

