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