1/*=============================================================================
2    Copyright (c) 2002-2003 Martin Wille
3    http://spirit.sourceforge.net/
4
5    Use, modification and distribution is subject to the Boost Software
6    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7    http://www.boost.org/LICENSE_1_0.txt)
8=============================================================================*/
9#ifndef BOOST_SPIRIT_CONDITIONS_IPP
10#define BOOST_SPIRIT_CONDITIONS_IPP
11
12///////////////////////////////////////////////////////////////////////////////
13#include <boost/spirit/home/classic/meta/parser_traits.hpp>
14#include <boost/spirit/home/classic/core/composite/epsilon.hpp>
15
16///////////////////////////////////////////////////////////////////////////////
17namespace boost { namespace spirit {
18
19BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
20
21    namespace impl {
22
23///////////////////////////////////////////////////////////////////////////////
24//
25// condition evaluation
26//
27///////////////////////////////////////////////////////////////////////////////
28    //////////////////////////////////
29    // condition_parser_selector, decides which parser to use for a condition
30    // If the template argument is a parser then that parser is used.
31    // If the template argument is a functor then a condition parser using
32    // the functor is chosen
33
34    template <typename T> struct embed_t_accessor
35    {
36        typedef typename T::embed_t type;
37    };
38
39    template <typename ConditionT>
40    struct condition_parser_selector
41    {
42        typedef
43            typename mpl::if_<
44                    is_parser<ConditionT>,
45                    ConditionT,
46                    condition_parser<ConditionT>
47                >::type
48            type;
49
50        typedef typename embed_t_accessor<type>::type embed_t;
51    };
52
53    //////////////////////////////////
54    // condition_evaluator, uses a parser to check wether a condition is met
55    // takes a parser or a functor that can be evaluated in boolean context
56    // as template parameter.
57
58    // JDG 4-15-03 refactored
59    template <typename ConditionT>
60    struct condition_evaluator
61    {
62        typedef condition_parser_selector<ConditionT>       selector_t;
63        typedef typename selector_t::type                   selected_t;
64        typedef typename selector_t::embed_t                cond_embed_t;
65
66        typedef typename boost::call_traits<cond_embed_t>::param_type
67            param_t;
68
69        condition_evaluator(param_t s) : cond(s) {}
70
71        /////////////////////////////
72        // evaluate, checks wether condition is met
73        // returns length of a match or a negative number for no-match
74        template <typename ScannerT>
75        std::ptrdiff_t
76        evaluate(ScannerT const &scan) const
77        {
78            typedef typename ScannerT::iterator_t iterator_t;
79            typedef typename parser_result<selected_t, ScannerT>::type cres_t;
80            iterator_t save(scan.first);
81            cres_t result = cond.parse(scan);
82            if (!result)            // reset the position if evaluation
83                scan.first = save;  // fails.
84            return result.length();
85        }
86
87        cond_embed_t cond;
88    };
89
90///////////////////////////////////////////////////////////////////////////////
91    } // namespace impl
92
93BOOST_SPIRIT_CLASSIC_NAMESPACE_END
94
95}} // namespace boost::spirit
96
97#endif
98