blob: d2d614adb740c67446a84751cab02a2788b3724b [file] [log] [blame]
/*=============================================================================
Copyright (c) 2002-2003 Martin Wille
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)
=============================================================================*/
#ifndef BOOST_SPIRIT_CONDITIONS_IPP
#define BOOST_SPIRIT_CONDITIONS_IPP
///////////////////////////////////////////////////////////////////////////////
#include <boost/spirit/home/classic/meta/parser_traits.hpp>
#include <boost/spirit/home/classic/core/composite/epsilon.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit {
BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
namespace impl {
///////////////////////////////////////////////////////////////////////////////
//
// condition evaluation
//
///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////
// condition_parser_selector, decides which parser to use for a condition
// If the template argument is a parser then that parser is used.
// If the template argument is a functor then a condition parser using
// the functor is chosen
template <typename T> struct embed_t_accessor
{
typedef typename T::embed_t type;
};
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
template <> struct embed_t_accessor<int>
{
typedef int type;
};
#endif
template <typename ConditionT>
struct condition_parser_selector
{
typedef
typename mpl::if_<
is_parser<ConditionT>,
ConditionT,
condition_parser<ConditionT>
>::type
type;
typedef typename embed_t_accessor<type>::type embed_t;
};
//////////////////////////////////
// condition_evaluator, uses a parser to check wether a condition is met
// takes a parser or a functor that can be evaluated in boolean context
// as template parameter.
// JDG 4-15-03 refactored
template <typename ConditionT>
struct condition_evaluator
{
typedef condition_parser_selector<ConditionT> selector_t;
typedef typename selector_t::type selected_t;
typedef typename selector_t::embed_t cond_embed_t;
typedef typename boost::call_traits<cond_embed_t>::param_type
param_t;
condition_evaluator(param_t s) : cond(s) {}
/////////////////////////////
// evaluate, checks wether condition is met
// returns length of a match or a negative number for no-match
template <typename ScannerT>
std::ptrdiff_t
evaluate(ScannerT const &scan) const
{
typedef typename ScannerT::iterator_t iterator_t;
typedef typename parser_result<selected_t, ScannerT>::type cres_t;
iterator_t save(scan.first);
cres_t result = cond.parse(scan);
if (!result) // reset the position if evaluation
scan.first = save; // fails.
return result.length();
}
cond_embed_t cond;
};
///////////////////////////////////////////////////////////////////////////////
} // namespace impl
BOOST_SPIRIT_CLASSIC_NAMESPACE_END
}} // namespace boost::spirit
#endif