1 /*=============================================================================
2 Copyright (c) 1998-2003 Joel de Guzman
3 http://spirit.sourceforge.net/
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
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>
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>
29 ///////////////////////////////////////////////////////////////////////////////
30 namespace boost { namespace spirit {
32 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
34 #if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1
37 BOOST_PP_ENUM_BINARY_PARAMS(
38 BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT,
39 typename ScannerT, = mpl::void_ BOOST_PP_INTERCEPT
44 #endif // BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1
46 ///////////////////////////////////////////////////////////////////////////
49 template <typename BaseT, typename DefaultT
50 , typename T0, typename T1, typename T2>
53 typedef typename mpl::if_<
54 is_base_and_derived<BaseT, T0>
57 is_base_and_derived<BaseT, T1>
60 is_base_and_derived<BaseT, T2>
68 template <typename T0, typename T1, typename T2>
71 typedef typename get_param<
72 parser_context_base, parser_context<>, T0, T1, T2>::type
76 template <typename T0, typename T1, typename T2>
79 typedef typename get_param<
80 parser_tag_base, parser_address_tag, T0, T1, T2>::type
84 template <typename T0, typename T1, typename T2>
87 typedef typename get_param<
88 scanner_base, scanner<>, T0, T1, T2>::type
92 ///////////////////////////////////////////////////////////////////////
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.
103 // <<< For framework use only. Not for public consumption. >>>
105 ///////////////////////////////////////////////////////////////////////
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
113 class rule_base; // forward declaration
115 class rule_base_access
117 #if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \
118 || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
128 friend class rule_base;
130 template <typename RuleT>
131 static typename RuleT::abstract_parser_t*
139 typename DerivedT // derived class
140 , typename EmbedT // how derived class is embedded
141 , typename T0 // see rule class
142 , typename T1 // see rule class
143 , typename T2 // see rule class
146 : public parser<DerivedT>
147 , public impl::get_context<T0, T1, T2>::type::base_t
148 , public context_aux<
149 typename impl::get_context<T0, T1, T2>::type, DerivedT>
150 , public impl::get_tag<T0, T1, T2>::type
154 typedef typename impl::get_scanner<T0, T1, T2>::type scanner_t;
155 typedef typename impl::get_context<T0, T1, T2>::type context_t;
156 typedef typename impl::get_tag<T0, T1, T2>::type tag_t;
158 typedef EmbedT embed_t;
159 typedef typename context_t::context_linker_t linked_context_t;
160 typedef typename linked_context_t::attr_t attr_t;
162 template <typename ScannerT>
165 typedef typename match_result<ScannerT, attr_t>::type type;
168 template <typename ScannerT>
169 typename parser_result<DerivedT, ScannerT>::type
170 parse(ScannerT const& scan) const
172 typedef parser_scanner_linker<ScannerT> linked_scanner_t;
173 typedef typename parser_result<DerivedT, ScannerT>::type result_t;
174 BOOST_SPIRIT_CONTEXT_PARSE(
175 scan, *this, linked_scanner_t, linked_context_t, result_t);
178 template <typename ScannerT>
179 typename parser_result<DerivedT, ScannerT>::type
180 parse_main(ScannerT const& scan) const
182 typename parser_result<DerivedT, ScannerT>::type hit;
184 // MWCW 8.3 needs this cast to be done through a pointer,
185 // not a reference. Otherwise, it will silently construct
186 // a temporary, causing an infinite runtime recursion.
187 DerivedT const* derived_this = static_cast<DerivedT const*>(this);
189 if (rule_base_access::get(*derived_this))
191 typename ScannerT::iterator_t s(scan.first);
192 hit = rule_base_access::get(*derived_this)
193 ->do_parse_virtual(scan);
194 scan.group_match(hit, this->id(), s, scan.first);
198 hit = scan.no_match();
204 ///////////////////////////////////////////////////////////////////////
206 // abstract_parser class
208 ///////////////////////////////////////////////////////////////////////
209 template <typename ScannerT, typename AttrT>
210 struct abstract_parser
213 virtual ~abstract_parser() {}
215 virtual typename match_result<ScannerT, AttrT>::type
216 do_parse_virtual(ScannerT const& scan) const = 0;
218 virtual abstract_parser*
222 ///////////////////////////////////////////////////////////////////////
224 // concrete_parser class
226 ///////////////////////////////////////////////////////////////////////
227 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
228 #pragma warning(push)
229 #pragma warning(disable:4512) //assignment operator could not be generated
232 template <typename ParserT, typename ScannerT, typename AttrT>
233 struct concrete_parser : abstract_parser<ScannerT, AttrT>
235 concrete_parser(ParserT const& p_) : p(p_) {}
236 virtual ~concrete_parser() {}
238 virtual typename match_result<ScannerT, AttrT>::type
239 do_parse_virtual(ScannerT const& scan) const
241 return p.parse(scan);
244 virtual abstract_parser<ScannerT, AttrT>*
247 return new concrete_parser(p);
250 typename ParserT::embed_t p;
253 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
257 #if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1
259 ///////////////////////////////////////////////////////////////////////
261 // This generates partial specializations for the class
265 // with an increasing number of different ScannerT template parameters
266 // and corresponding do_parse_virtual function declarations for each
267 // of the different required scanner types:
269 // template <typename ScannerT0, ..., typename AttrT>
270 // struct abstract_parser<scanner_list<ScannerT0, ...>, AttrT>
272 // abstract_parser() {}
273 // virtual ~abstract_parser() {}
275 // virtual typename match_result<ScannerT0, AttrT>::type
276 // do_parse_virtual(ScannerT0 const &scan) const = 0;
278 // virtual abstract_parser*
279 // clone() const = 0;
284 ///////////////////////////////////////////////////////////////////////
285 #define BOOST_SPIRIT_RULE_ENUM_DOPARSE_A(z, N, _) \
286 virtual typename match_result< \
287 BOOST_PP_CAT(ScannerT, N), AttrT \
290 BOOST_PP_CAT(ScannerT, N) const& scan) const = 0; \
292 #define BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS(z, N, _) \
294 BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), typename ScannerT), \
297 struct abstract_parser< \
299 BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT) \
304 abstract_parser() {} \
305 virtual ~abstract_parser() {} \
307 BOOST_PP_REPEAT_ ## z( \
308 BOOST_PP_INC(N), BOOST_SPIRIT_RULE_ENUM_DOPARSE_A, _) \
310 virtual abstract_parser* \
314 BOOST_PP_REPEAT_FROM_TO(1, BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT,
315 BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS, _)
317 #undef BOOST_SPIRIT_RULE_ENUM_DOPARSE_A
318 #undef BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS
319 ///////////////////////////////////////////////////////////////////////
321 ///////////////////////////////////////////////////////////////////////
323 // This generates partial specializations for the class
327 // with an increasing number of different ScannerT template parameters
328 // and corresponding do_parse_virtual function declarations for each
329 // of the different required scanner types:
332 // typename ParserT, typename ScannerT0, ..., typename AttrT
334 // struct concrete_parser<
335 // ParserT, scanner_list<ScannerT0, ...>, AttrT
337 // : public abstract_parser<scanner_list<ScannerT0, ...>, AttrT>
339 // concrete_parser(ParserT const& p_) : p(p_) {}
340 // virtual ~concrete_parser() {}
342 // virtual typename match_result<ScannerT0, AttrT>::type
343 // do_parse_virtual(ScannerT0 const &scan) const
344 // { return p.parse(scan); }
346 // virtual abstract_parser<scanner_list<ScannerT0, ...>, AttrT>*
349 // return new concrete_parser(p);
354 // typename ParserT::embed_t p;
357 ///////////////////////////////////////////////////////////////////////
358 #define BOOST_SPIRIT_RULE_ENUM_DOPARSE_C(z, N, _) \
359 virtual typename match_result< \
360 BOOST_PP_CAT(ScannerT, N), AttrT \
363 BOOST_PP_CAT(ScannerT, N) const& scan) const \
364 { return p.parse(scan); } \
366 #define BOOST_SPIRIT_ENUM_CONCRETE_PARSERS(z, N, _) \
369 BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), typename ScannerT), \
372 struct concrete_parser< \
375 BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT) \
381 BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT) \
386 concrete_parser(ParserT const& p_) : p(p_) {} \
387 virtual ~concrete_parser() {} \
389 BOOST_PP_REPEAT_ ## z( \
390 BOOST_PP_INC(N), BOOST_SPIRIT_RULE_ENUM_DOPARSE_C, _) \
392 virtual abstract_parser< \
394 BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT) \
400 return new concrete_parser(p); \
403 typename ParserT::embed_t p; \
406 BOOST_PP_REPEAT_FROM_TO(1, BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT,
407 BOOST_SPIRIT_ENUM_CONCRETE_PARSERS, _)
409 #undef BOOST_SPIRIT_ENUM_CONCRETE_PARSERS
410 #undef BOOST_SPIRIT_RULE_ENUM_DOPARSE_C
411 ///////////////////////////////////////////////////////////////////////
413 #endif // BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1
417 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
419 }} // namespace boost::spirit