// file      : xsde/cxx/parser/elements.hxx
// author    : Boris Kolpackov <boris@codesynthesis.com>
// copyright : Copyright (c) 2005-2007 Code Synthesis Tools CC
// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file

#ifndef XSDE_CXX_PARSER_ELEMENTS_HXX
#define XSDE_CXX_PARSER_ELEMENTS_HXX

#include <xsde/cxx/config.hxx>
#include <xsde/cxx/ro-string.hxx>

#ifdef XSDE_VALIDATION_PARSER
#  include <xsde/cxx/schema-error.hxx>
#endif

#ifndef XSDE_EXCEPTIONS
#  include <xsde/cxx/sys-error.hxx>
#  include <xsde/cxx/parser/error.hxx>
#endif

namespace xsde
{
  namespace cxx
  {
    namespace parser
    {
      // pre() and post() are overridable pre/post callbacks, i.e., the
      // derived parser can override them without calling the base version.
      // _pre() and _post() are not overridable pre/post callbacks in the
      // sense that the derived parser may override them but has to call
      // the base version. The call sequence is as shown below:
      //
      // pre ()
      // _pre ()
      // _post ()
      // post ()
      //
      struct parser_base
      {
        virtual
        ~parser_base ();

        virtual void
        pre ();

        virtual void
        _pre ();

        virtual void
        _start_element (const ro_string& ns,
                        const ro_string& name) = 0;

        virtual void
        _end_element (const ro_string& ns,
                      const ro_string& name) = 0;

        virtual void
        _attribute (const ro_string& ns,
                    const ro_string& name,
                    const ro_string& value) = 0;

        virtual void
        _characters (const ro_string&) = 0;

        virtual void
        _post ();

        // The post() signature varies depending on the parser return
        // type.
        //

        // Implementation callbacks for _pre and _post. The _pre and _post
        // callbacks should never be called directly. Instead, the *_impl
        // versions should be used. By default _pre_impl and _post_impl
        // simply call _pre and _post respectively.
        //
        virtual void
        _pre_impl ();

        virtual void
        _post_impl ();


        // Error handling via codes.
        //
#ifndef XSDE_EXCEPTIONS
      public:
        error
        _error () const;

        // Set application error.
        //
        void
        _app_error (int);

        int
        _app_error () const;
#endif

        // System error.
        //
#ifndef XSDE_EXCEPTIONS
      public:
        typedef cxx::sys_error::value sys_error_t;

        sys_error_t
        _sys_error () const;

        void
        _sys_error (sys_error_t);
#endif

        // Internal error state for schema validation. Do not call
        // from client code.
        //
#ifdef XSDE_VALIDATION_PARSER
      public:
        typedef cxx::schema_error::value schema_error_t;

        schema_error_t
        _schema_error () const;

        void
        _schema_error (schema_error_t);
#endif

        // Implementation details.
        //
#if defined(XSDE_VALIDATION_PARSER) || !defined(XSDE_EXCEPTIONS)
      public:
        enum error_type_t
        {
          error_none,
          error_sys,
          error_schema,
          error_app
        };

        parser_base ();

        error_type_t
        _error_type () const;

        bool
        _error_p () const;

        void
        _copy_error (const parser_base* src);

      protected:
        error_type_t error_type_;

        union
        {
#ifndef XSDE_EXCEPTIONS
          sys_error_t sys;
#endif
#ifdef XSDE_VALIDATION_PARSER
          schema_error_t schema;
#endif
#ifndef XSDE_EXCEPTIONS
          int app;
#endif
        } error_code_;

#endif // XSDE_VALIDATION_PARSER || !XSDE_EXCEPTIONS
      };
    }
  }
}

#include <xsde/cxx/parser/elements.ixx>

#endif  // XSDE_CXX_PARSER_ELEMENTS_HXX
