source: NonGTP/Boost/boost/spirit/core/non_terminal/impl/subrule.ipp @ 857

Revision 857, 6.4 KB checked in by igarcia, 18 years ago (diff)
Line 
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
15    template <typename FirstT, typename RestT>
16    struct subrule_list;
17
18    template <int ID, typename DefT, typename ContextT>
19    struct subrule_parser;
20
21    namespace impl {
22
23    #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
24
25        template <int N, typename ListT>
26        struct get_subrule;
27
28        template <int N, typename ListT>
29        struct get_subrule_chooser
30        {
31                static ListT t();
32                static char test(nil_t);
33                static int  test(...);
34
35                //  Set value to
36                //      0: ListT is empty
37                //      1: ListT's first item has same ID
38                //      2: ListT's first item has a different ID
39
40                enum
41                {
42                id = ListT::first_t::id,
43                is_same_id = N == id,
44                    is_nil_t = sizeof(char) == sizeof(test(t())),
45                    value = is_nil_t ? 0 : (is_same_id ? 1 : 2)
46                };
47          };
48
49        template <int N>
50        struct subrule_chooser;
51
52        template <>
53        struct subrule_chooser<0>
54        {
55            //  First case. ListT is empty
56
57            template <int N, typename ListT>
58            struct result
59            { typedef nil_t type; };
60        };
61
62        template <>
63        struct subrule_chooser<1>
64        {
65            //  Second case. ListT is non-empty and the list's
66            //  first item has the ID we are looking for.
67
68            template <int N, typename ListT>
69            struct result
70            { typedef typename ListT::first_t::def_t type; };
71        };
72
73        template <>
74        struct subrule_chooser<2>
75        {
76            //  Third case. ListT is non-empty but the list's
77            //  first item does not have the ID we are looking for.
78
79            template <int N, typename ListT>
80            struct result
81            { typedef typename get_subrule<N, ListT::rest_t>::type type; };
82        };
83
84        template <int N, typename ListT>
85        struct get_subrule
86        {
87            enum { n = get_subrule_chooser<N, ListT>::value };
88            typedef typename subrule_chooser<n>::template
89                result<N, ListT>::type type;
90        };
91
92    #else
93
94        template <int N, typename ListT>
95        struct get_subrule
96        {
97            //  First case. ListT is non-empty but the list's
98            //  first item does not have the ID we are looking for.
99
100            typedef typename get_subrule<N, typename ListT::rest_t>::type type;
101        };
102
103        template <int ID, typename DefT, typename ContextT, typename RestT>
104        struct get_subrule<
105            ID,
106            subrule_list<
107                subrule_parser<ID, DefT, ContextT>,
108                RestT> >
109        {
110            //  Second case. ListT is non-empty and the list's
111            //  first item has the ID we are looking for.
112
113            typedef DefT type;
114        };
115
116        template <int ID>
117        struct get_subrule<ID, nil_t>
118        {
119            //  Third case. ListT is empty
120            typedef nil_t type;
121        };
122
123    #endif
124
125        template <typename T1, typename T2>
126        struct get_result_t {
127
128        //  If the result type dictated by the context is nil_t (no closures
129        //  present), then the whole subrule_parser return type is equal to
130        //  the return type of the right hand side of this subrule_parser,
131        //  otherwise it is equal to the dictated return value.
132
133            typedef typename mpl::if_<
134                boost::is_same<T1, nil_t>, T2, T1
135            >::type type;
136        };
137
138        template <int ID, typename ScannerT, typename ContextResultT>
139        struct get_subrule_result
140        {
141            typedef typename
142                impl::get_subrule<ID, typename ScannerT::list_t>::type
143            parser_t;
144
145            typedef typename parser_result<parser_t, ScannerT>::type
146            def_result_t;
147
148            typedef typename match_result<ScannerT, ContextResultT>::type
149            context_result_t;
150
151            typedef typename get_result_t<context_result_t, def_result_t>::type
152            type;
153        };
154
155        template <typename DefT, typename ScannerT, typename ContextResultT>
156        struct get_subrule_parser_result
157        {
158            typedef typename parser_result<DefT, ScannerT>::type
159            def_result_t;
160
161            typedef typename match_result<ScannerT, ContextResultT>::type
162            context_result_t;
163
164            typedef typename get_result_t<context_result_t, def_result_t>::type
165            type;
166        };
167
168        template <typename SubruleT, int ID>
169        struct same_subrule_id
170        {
171            BOOST_STATIC_CONSTANT(bool, value = (SubruleT::id == ID));
172        };
173
174        template <typename RT, typename ScannerT, int ID>
175        struct parse_subrule
176        {
177            template <typename ListT>
178            static void
179            do_parse(RT& r, ScannerT const& scan, ListT const& list, mpl::true_)
180            {
181                r = list.first.rhs.parse(scan);
182            }
183
184            template <typename ListT>
185            static void
186            do_parse(RT& r, ScannerT const& scan, ListT const& list, mpl::false_)
187            {
188                typedef typename ListT::rest_t::first_t subrule_t;
189                mpl::bool_<same_subrule_id<subrule_t, ID>::value> same_id;
190                do_parse(r, scan, list.rest, same_id);
191            }
192
193            static void
194            do_(RT& r, ScannerT const& scan)
195            {
196                typedef typename ScannerT::list_t::first_t subrule_t;
197                mpl::bool_<same_subrule_id<subrule_t, ID>::value> same_id;
198                do_parse(r, scan, scan.list, same_id);
199            }
200        };
201
202}}} // namespace boost::spirit::impl
203
204#endif
205
Note: See TracBrowser for help on using the repository browser.