1/*=============================================================================
2    Copyright (c) 2002-2003 Joel de Guzman
3    Copyright (c) 2002-2003 Hartmut Kaiser
4    http://spirit.sourceforge.net/
5
6    Use, modification and distribution is subject to the Boost Software
7    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8    http://www.boost.org/LICENSE_1_0.txt)
9=============================================================================*/
10#if !defined(BOOST_SPIRIT_SUBRULE_IPP)
11#define BOOST_SPIRIT_SUBRULE_IPP
12
13#include <boost/mpl/if.hpp>
14
15namespace boost { namespace spirit {
16
17BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
18
19    template <typename FirstT, typename RestT>
20    struct subrule_list;
21
22    template <int ID, typename DefT, typename ContextT>
23    struct subrule_parser;
24
25    namespace impl {
26
27
28        template <int N, typename ListT>
29        struct get_subrule
30        {
31            //  First case. ListT is non-empty but the list's
32            //  first item does not have the ID we are looking for.
33
34            typedef typename get_subrule<N, typename ListT::rest_t>::type type;
35        };
36
37        template <int ID, typename DefT, typename ContextT, typename RestT>
38        struct get_subrule<
39            ID,
40            subrule_list<
41                subrule_parser<ID, DefT, ContextT>,
42                RestT> >
43        {
44            //  Second case. ListT is non-empty and the list's
45            //  first item has the ID we are looking for.
46
47            typedef DefT type;
48        };
49
50        template <int ID>
51        struct get_subrule<ID, nil_t>
52        {
53            //  Third case. ListT is empty
54            typedef nil_t type;
55        };
56
57
58        template <typename T1, typename T2>
59        struct get_result_t {
60
61        //  If the result type dictated by the context is nil_t (no closures
62        //  present), then the whole subrule_parser return type is equal to
63        //  the return type of the right hand side of this subrule_parser,
64        //  otherwise it is equal to the dictated return value.
65
66            typedef typename mpl::if_<
67                boost::is_same<T1, nil_t>, T2, T1
68            >::type type;
69        };
70
71        template <int ID, typename ScannerT, typename ContextResultT>
72        struct get_subrule_result
73        {
74            typedef typename
75                impl::get_subrule<ID, typename ScannerT::list_t>::type
76            parser_t;
77
78            typedef typename parser_result<parser_t, ScannerT>::type
79            def_result_t;
80
81            typedef typename match_result<ScannerT, ContextResultT>::type
82            context_result_t;
83
84            typedef typename get_result_t<context_result_t, def_result_t>::type
85            type;
86        };
87
88        template <typename DefT, typename ScannerT, typename ContextResultT>
89        struct get_subrule_parser_result
90        {
91            typedef typename parser_result<DefT, ScannerT>::type
92            def_result_t;
93
94            typedef typename match_result<ScannerT, ContextResultT>::type
95            context_result_t;
96
97            typedef typename get_result_t<context_result_t, def_result_t>::type
98            type;
99        };
100
101        template <typename SubruleT, int ID>
102        struct same_subrule_id
103        {
104            BOOST_STATIC_CONSTANT(bool, value = (SubruleT::id == ID));
105        };
106
107        template <typename RT, typename ScannerT, int ID>
108        struct parse_subrule
109        {
110            template <typename ListT>
111            static void
112            do_parse(RT& r, ScannerT const& scan, ListT const& list, mpl::true_)
113            {
114                r = list.first.rhs.parse(scan);
115            }
116
117            template <typename ListT>
118            static void
119            do_parse(RT& r, ScannerT const& scan, ListT const& list, mpl::false_)
120            {
121                typedef typename ListT::rest_t::first_t subrule_t;
122                mpl::bool_<same_subrule_id<subrule_t, ID>::value> same_id;
123                do_parse(r, scan, list.rest, same_id);
124            }
125
126            static void
127            do_(RT& r, ScannerT const& scan)
128            {
129                typedef typename ScannerT::list_t::first_t subrule_t;
130                mpl::bool_<same_subrule_id<subrule_t, ID>::value> same_id;
131                do_parse(r, scan, scan.list, same_id);
132            }
133        };
134
135}
136
137BOOST_SPIRIT_CLASSIC_NAMESPACE_END
138
139}} // namespace boost::spirit::impl
140
141#endif
142
143