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

Revision 857, 18.2 KB checked in by igarcia, 18 years ago (diff)
Line 
1/*=============================================================================
2    Copyright (c) 1998-2003 Joel de Guzman
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#if !defined(BOOST_SPIRIT_RULE_IPP)
10#define BOOST_SPIRIT_RULE_IPP
11
12#if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1
13#include <boost/preprocessor/repeat.hpp>
14#include <boost/preprocessor/repeat_from_to.hpp>
15#include <boost/preprocessor/enum_params.hpp>
16#include <boost/preprocessor/enum_params_with_defaults.hpp>
17#include <boost/preprocessor/facilities/intercept.hpp>
18#include <boost/preprocessor/inc.hpp>
19#include <boost/preprocessor/cat.hpp>
20#endif
21
22#include <boost/spirit/core/parser.hpp>
23#include <boost/spirit/core/scanner/scanner.hpp>
24#include <boost/spirit/core/non_terminal/parser_context.hpp>
25#include <boost/spirit/core/non_terminal/parser_id.hpp>
26#include <boost/type_traits/is_base_and_derived.hpp>
27
28///////////////////////////////////////////////////////////////////////////////
29namespace boost { namespace spirit {
30
31#if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1
32
33        template <
34            BOOST_PP_ENUM_BINARY_PARAMS(
35                BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT,
36                typename ScannerT, = mpl::void_ BOOST_PP_INTERCEPT
37            )
38        >
39        struct scanner_list;
40
41#endif // BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1
42
43    ///////////////////////////////////////////////////////////////////////////
44    namespace impl
45    {
46        template <typename BaseT, typename DefaultT
47            , typename T0, typename T1, typename T2>
48        struct get_param
49        {
50            typedef typename mpl::if_<
51                is_base_and_derived<BaseT, T0>
52              , T0
53              , typename mpl::if_<
54                    is_base_and_derived<BaseT, T1>
55                  , T1
56                  , typename mpl::if_<
57                        is_base_and_derived<BaseT, T2>
58                      , T2
59                      , DefaultT
60                    >::type
61                >::type
62            >::type type;
63        };
64
65        template <typename T0, typename T1, typename T2>
66        struct get_context
67        {
68            typedef typename get_param<
69                parser_context_base, parser_context<>, T0, T1, T2>::type
70            type;
71        };
72
73        template <typename T0, typename T1, typename T2>
74        struct get_tag
75        {
76            typedef typename get_param<
77                parser_tag_base, parser_address_tag, T0, T1, T2>::type
78            type;
79        };
80
81        template <typename T0, typename T1, typename T2>
82        struct get_scanner
83        {
84            typedef typename get_param<
85                scanner_base, scanner<>, T0, T1, T2>::type
86            type;
87        };
88
89        ///////////////////////////////////////////////////////////////////////
90        //
91        //  rule_base class
92        //
93        //      The rule_base class implements the basic plumbing for rules
94        //      minus the storage mechanism. It is up to the derived class
95        //      to actually store the definition somewhere. The rule_base
96        //      class assumes that the derived class provides a get() function
97        //      that will return a pointer to a parser. The get() function
98        //      may return NULL. See rule below for details.
99        //
100        //      <<< For framework use only. Not for public consumption. >>>
101        //
102        ///////////////////////////////////////////////////////////////////////
103        template <
104            typename DerivedT       // derived class
105          , typename EmbedT         // how derived class is embedded
106          , typename T0 = nil_t     // see rule class
107          , typename T1 = nil_t     // see rule class
108          , typename T2 = nil_t     // see rule class
109        >
110        class rule_base; // forward declaration
111
112        class rule_base_access
113        {
114#if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \
115    || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
116        public: // YUCK!
117#else
118            template <
119                typename DerivedT
120              , typename EmbedT
121              , typename T0
122              , typename T1
123              , typename T2
124            >
125           friend class rule_base;
126#endif
127            template <typename RuleT>
128            static typename RuleT::abstract_parser_t*
129            get(RuleT const& r)
130            {
131                return r.get();
132            }
133        };
134
135        template <
136            typename DerivedT       // derived class
137          , typename EmbedT         // how derived class is embedded
138          , typename T0             // see rule class
139          , typename T1             // see rule class
140          , typename T2             // see rule class
141        >
142        class rule_base
143            : public parser<DerivedT>
144            , public impl::get_context<T0, T1, T2>::type::base_t
145            , public context_aux<
146                typename impl::get_context<T0, T1, T2>::type, DerivedT>
147            , public impl::get_tag<T0, T1, T2>::type
148        {
149        public:
150
151            typedef typename impl::get_scanner<T0, T1, T2>::type scanner_t;
152            typedef typename impl::get_context<T0, T1, T2>::type context_t;
153            typedef typename impl::get_tag<T0, T1, T2>::type tag_t;
154
155            typedef EmbedT embed_t;
156            typedef typename context_t::context_linker_t linked_context_t;
157            typedef typename linked_context_t::attr_t attr_t;
158
159            template <typename ScannerT>
160            struct result
161            {
162                typedef typename match_result<ScannerT, attr_t>::type type;
163            };
164
165            template <typename ScannerT>
166            typename parser_result<DerivedT, ScannerT>::type
167            parse(ScannerT const& scan) const
168            {
169                typedef parser_scanner_linker<ScannerT> linked_scanner_t;
170                typedef typename parser_result<DerivedT, ScannerT>::type result_t;
171                BOOST_SPIRIT_CONTEXT_PARSE(
172                    scan, *this, linked_scanner_t, linked_context_t, result_t);
173            }
174
175            template <typename ScannerT>
176            typename parser_result<DerivedT, ScannerT>::type
177            parse_main(ScannerT const& scan) const
178            {
179                typename parser_result<DerivedT, ScannerT>::type hit;
180
181                //  MWCW 8.3 needs this cast to be done through a pointer,
182                //  not a reference. Otherwise, it will silently construct
183                //  a temporary, causing an infinite runtime recursion.
184                DerivedT const* derived_this = static_cast<DerivedT const*>(this);
185
186                if (rule_base_access::get(*derived_this))
187                {
188                    typename ScannerT::iterator_t s(scan.first);
189                    hit = rule_base_access::get(*derived_this)
190                            ->do_parse_virtual(scan);
191                    scan.group_match(hit, this->id(), s, scan.first);
192                }
193                else
194                {
195                    hit = scan.no_match();
196                }
197                return hit;
198            }
199        };
200
201        ///////////////////////////////////////////////////////////////////////
202        //
203        //  abstract_parser class
204        //
205        ///////////////////////////////////////////////////////////////////////
206        template <typename ScannerT, typename AttrT>
207        struct abstract_parser
208        {
209            abstract_parser() {}
210            virtual ~abstract_parser() {}
211
212            virtual typename match_result<ScannerT, AttrT>::type
213            do_parse_virtual(ScannerT const& scan) const = 0;
214
215            virtual abstract_parser*
216            clone() const = 0;
217        };
218
219        ///////////////////////////////////////////////////////////////////////
220        //
221        //  concrete_parser class
222        //
223        ///////////////////////////////////////////////////////////////////////
224        template <typename ParserT, typename ScannerT, typename AttrT>
225        struct concrete_parser : abstract_parser<ScannerT, AttrT>
226        {
227            concrete_parser(ParserT const& p) : p(p) {}
228            virtual ~concrete_parser() {}
229
230            virtual typename match_result<ScannerT, AttrT>::type
231            do_parse_virtual(ScannerT const& scan) const
232            {
233                return p.parse(scan);
234            }
235
236            virtual abstract_parser<ScannerT, AttrT>*
237            clone() const
238            {
239                return new concrete_parser(p);
240            }
241
242            typename ParserT::embed_t p;
243        };
244
245#if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1
246
247        ///////////////////////////////////////////////////////////////////////
248        //
249        //  This generates partial specializations for the class
250        //
251        //          abstract_parser
252        //
253        //  with an increasing number of different ScannerT template parameters
254        //  and corresponding do_parse_virtual function declarations for each
255        //  of the different required scanner types:
256        //
257        //      template <typename ScannerT0, ..., typename AttrT>
258        //      struct abstract_parser<scanner_list<ScannerT0, ...>, AttrT>
259        //      {
260        //          abstract_parser() {}
261        //          virtual ~abstract_parser() {}
262        //
263        //          virtual typename match_result<ScannerT0, AttrT>::type
264        //          do_parse_virtual(ScannerT0 const &scan) const = 0;
265        //
266        //          virtual abstract_parser*
267        //          clone() const = 0;
268        //
269        //          ...
270        //      };
271        //
272        ///////////////////////////////////////////////////////////////////////
273        #define BOOST_SPIRIT_RULE_ENUM_DOPARSE_A(z, N, _)                       \
274                virtual typename match_result<                                  \
275                    BOOST_PP_CAT(ScannerT, N), AttrT                            \
276                >::type                                                         \
277                do_parse_virtual(                                               \
278                    BOOST_PP_CAT(ScannerT, N) const& scan) const = 0;           \
279
280        #define BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS(z, N, _)                     \
281            template <                                                          \
282                BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), typename ScannerT),  \
283                typename AttrT                                                  \
284            >                                                                   \
285            struct abstract_parser<                                             \
286                scanner_list<                                                   \
287                    BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT)        \
288                >,                                                              \
289                AttrT                                                           \
290            >                                                                   \
291            {                                                                   \
292                abstract_parser() {}                                            \
293                virtual ~abstract_parser() {}                                   \
294                                                                                \
295                BOOST_PP_REPEAT_ ## z(                                          \
296                    BOOST_PP_INC(N), BOOST_SPIRIT_RULE_ENUM_DOPARSE_A, _)       \
297                                                                                \
298                virtual abstract_parser*                                        \
299                clone() const = 0;                                              \
300            };                                                                  \
301
302        BOOST_PP_REPEAT_FROM_TO(1, BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT,
303            BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS, _)
304
305        #undef BOOST_SPIRIT_RULE_ENUM_DOPARSE_A
306        #undef BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS
307        ///////////////////////////////////////////////////////////////////////
308
309        ///////////////////////////////////////////////////////////////////////
310        //
311        //  This generates partial specializations for the class
312        //
313        //          concrete_parser
314        //
315        //  with an increasing number of different ScannerT template parameters
316        //  and corresponding do_parse_virtual function declarations for each
317        //  of the different required scanner types:
318        //
319        //      template <
320        //          typename ParserT, typename ScannerT0, ..., typename AttrT
321        //      >
322        //      struct concrete_parser<
323        //          ParserT, scanner_list<ScannerT0, ...>, AttrT
324        //      >
325        //      :   public abstract_parser<scanner_list<ScannerT0, ...>, AttrT>
326        //      {
327        //          concrete_parser(ParserT const& p_) : p(p_) {}
328        //          virtual ~concrete_parser() {}
329        //
330        //          virtual typename match_result<ScannerT0, AttrT>::type
331        //          do_parse_virtual(ScannerT0 const &scan) const
332        //          { return p.parse(scan); }
333        //
334        //          virtual abstract_parser<scanner_list<ScannerT0, ...>, AttrT>*
335        //          clone() const
336        //          {
337        //              return new concrete_parser(p);
338        //          }
339        //
340        //          ...
341        //
342        //          typename ParserT::embed_t p;
343        //      };
344        //
345        ///////////////////////////////////////////////////////////////////////
346        #define BOOST_SPIRIT_RULE_ENUM_DOPARSE_C(z, N, _)                       \
347                virtual typename match_result<                                  \
348                    BOOST_PP_CAT(ScannerT, N), AttrT                            \
349                >::type                                                         \
350                do_parse_virtual(                                               \
351                    BOOST_PP_CAT(ScannerT, N) const& scan) const                \
352                { return p.parse(scan); }                                       \
353
354        #define BOOST_SPIRIT_ENUM_CONCRETE_PARSERS(z, N, _)                     \
355            template <                                                          \
356                typename ParserT,                                               \
357                BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), typename ScannerT),  \
358                typename AttrT                                                  \
359            >                                                                   \
360            struct concrete_parser<                                             \
361                ParserT,                                                        \
362                scanner_list<                                                   \
363                    BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT)        \
364                >,                                                              \
365                AttrT                                                           \
366            >                                                                   \
367            :   abstract_parser<                                                \
368                    scanner_list<                                               \
369                        BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT)    \
370                    >,                                                          \
371                    AttrT                                                       \
372                >                                                               \
373            {                                                                   \
374                concrete_parser(ParserT const& p_) : p(p_) {}                   \
375                virtual ~concrete_parser() {}                                   \
376                                                                                \
377                BOOST_PP_REPEAT_ ## z(                                          \
378                    BOOST_PP_INC(N), BOOST_SPIRIT_RULE_ENUM_DOPARSE_C, _)       \
379                                                                                \
380                virtual abstract_parser<                                        \
381                    scanner_list<                                               \
382                        BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT)    \
383                    >,                                                          \
384                    AttrT                                                       \
385                >*                                                              \
386                clone() const                                                   \
387                {                                                               \
388                    return new concrete_parser(p);                              \
389                }                                                               \
390                                                                                \
391                typename ParserT::embed_t p;                                    \
392            };                                                                  \
393
394        BOOST_PP_REPEAT_FROM_TO(1, BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT,
395            BOOST_SPIRIT_ENUM_CONCRETE_PARSERS, _)
396
397        #undef BOOST_SPIRIT_ENUM_CONCRETE_PARSERS
398        #undef BOOST_SPIRIT_RULE_ENUM_DOPARSE_C
399        ///////////////////////////////////////////////////////////////////////
400
401#endif // BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1
402
403    } // namespace impl
404
405}} // namespace boost::spirit
406
407#endif
Note: See TracBrowser for help on using the repository browser.