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