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

// attr_matcher.hpp

//

//  Copyright 2007 Eric Niebler.

//  Copyright 2007 David Jenkins.

//

//  Distributed under 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)



#ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ATTR_MATCHER_HPP_EAN_06_09_2007

#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_ATTR_MATCHER_HPP_EAN_06_09_2007



// MS compatible compilers support #pragma once

#if defined(_MSC_VER) && (_MSC_VER >= 1020)

# pragma once

#endif



#include <boost/xpressive/detail/detail_fwd.hpp>

#include <boost/xpressive/detail/core/quant_style.hpp>

#include <boost/xpressive/detail/core/state.hpp>

#include <boost/xpressive/detail/utility/symbols.hpp>



namespace boost { namespace xpressive { namespace detail

{



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

    // char_translate

    //

    template<typename Traits, bool ICase>

    struct char_translate

    {

        typedef typename Traits::char_type char_type;

        Traits const &traits_;



        explicit char_translate(Traits const &traits)

          : traits_(traits)

        {}



        char_type operator ()(char_type ch1) const

        {

            return this->traits_.translate(ch1);

        }

    };



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

    // char_translate

    //

    template<typename Traits>

    struct char_translate<Traits, true>

    {

        typedef typename Traits::char_type char_type;

        Traits const &traits_;



        explicit char_translate(Traits const &traits)

          : traits_(traits)

        {}



        char_type operator ()(char_type ch1) const

        {

            return this->traits_.translate_nocase(ch1);

        }

    };



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

    // attr_matcher

    //  Note: the Matcher is a std::map

    template<typename Matcher, typename Traits, bool ICase>

    struct attr_matcher

      : quant_style<quant_none, 0, false>

    {

        typedef typename Matcher::value_type::second_type const* result_type;



        attr_matcher(int slot, Matcher const &matcher, Traits const& traits)

          : slot_(slot-1)

        {

            char_translate<Traits, ICase> trans(traits);

            this->sym_.load(matcher, trans);

        }



        template<typename BidiIter, typename Next>

        bool match(match_state<BidiIter> &state, Next const &next) const

        {

            BidiIter tmp = state.cur_;

            char_translate<Traits, ICase> trans(traits_cast<Traits>(state));

            result_type const &result = this->sym_(state.cur_, state.end_, trans);

            if(result)

            {

                void const *old_slot = state.attr_context_.attr_slots_[this->slot_];

                state.attr_context_.attr_slots_[this->slot_] = &*result;

                if(next.match(state))

                {

                    return true;

                }

                state.attr_context_.attr_slots_[this->slot_] = old_slot;

            }

            state.cur_ = tmp;

            return false;

        }



        int slot_;

        boost::xpressive::detail::symbols<Matcher> sym_;

    };



}}}



#endif

