422 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			422 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| /*=============================================================================
 | |
|     Copyright (c) 1998-2003 Joel de Guzman
 | |
|     http://spirit.sourceforge.net/
 | |
| 
 | |
|     Use, modification and distribution is subject to the Boost Software
 | |
|     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
 | |
|     http://www.boost.org/LICENSE_1_0.txt)
 | |
| =============================================================================*/
 | |
| #if !defined(BOOST_SPIRIT_RULE_IPP)
 | |
| #define BOOST_SPIRIT_RULE_IPP
 | |
| 
 | |
| #if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1
 | |
| #include <boost/preprocessor/repeat.hpp>
 | |
| #include <boost/preprocessor/repeat_from_to.hpp>
 | |
| #include <boost/preprocessor/enum_params.hpp>
 | |
| #include <boost/preprocessor/enum_params_with_defaults.hpp>
 | |
| #include <boost/preprocessor/facilities/intercept.hpp>
 | |
| #include <boost/preprocessor/inc.hpp>
 | |
| #include <boost/preprocessor/cat.hpp>
 | |
| #endif
 | |
| 
 | |
| #include <boost/spirit/home/classic/core/parser.hpp>
 | |
| #include <boost/spirit/home/classic/core/scanner/scanner.hpp>
 | |
| #include <boost/spirit/home/classic/core/non_terminal/parser_context.hpp>
 | |
| #include <boost/spirit/home/classic/core/non_terminal/parser_id.hpp>
 | |
| #include <boost/type_traits/is_base_and_derived.hpp>
 | |
| #include <boost/mpl/if.hpp>
 | |
| 
 | |
| ///////////////////////////////////////////////////////////////////////////////
 | |
| namespace boost { namespace spirit {
 | |
| 
 | |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
 | |
| 
 | |
| #if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1
 | |
| 
 | |
|         template <
 | |
|             BOOST_PP_ENUM_BINARY_PARAMS(
 | |
|                 BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT,
 | |
|                 typename ScannerT, = mpl::void_ BOOST_PP_INTERCEPT
 | |
|             )
 | |
|         >
 | |
|         struct scanner_list;
 | |
| 
 | |
| #endif // BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1
 | |
| 
 | |
|     ///////////////////////////////////////////////////////////////////////////
 | |
|     namespace impl
 | |
|     {
 | |
|         template <typename BaseT, typename DefaultT
 | |
|             , typename T0, typename T1, typename T2>
 | |
|         struct get_param
 | |
|         {
 | |
|             typedef typename mpl::if_<
 | |
|                 is_base_and_derived<BaseT, T0>
 | |
|               , T0
 | |
|               , typename mpl::if_<
 | |
|                     is_base_and_derived<BaseT, T1>
 | |
|                   , T1
 | |
|                   , typename mpl::if_<
 | |
|                         is_base_and_derived<BaseT, T2>
 | |
|                       , T2
 | |
|                       , DefaultT
 | |
|                     >::type
 | |
|                 >::type
 | |
|             >::type type;
 | |
|         };
 | |
| 
 | |
|         template <typename T0, typename T1, typename T2>
 | |
|         struct get_context
 | |
|         {
 | |
|             typedef typename get_param<
 | |
|                 parser_context_base, parser_context<>, T0, T1, T2>::type
 | |
|             type;
 | |
|         };
 | |
| 
 | |
|         template <typename T0, typename T1, typename T2>
 | |
|         struct get_tag
 | |
|         {
 | |
|             typedef typename get_param<
 | |
|                 parser_tag_base, parser_address_tag, T0, T1, T2>::type
 | |
|             type;
 | |
|         };
 | |
| 
 | |
|         template <typename T0, typename T1, typename T2>
 | |
|         struct get_scanner
 | |
|         {
 | |
|             typedef typename get_param<
 | |
|                 scanner_base, scanner<>, T0, T1, T2>::type
 | |
|             type;
 | |
|         };
 | |
| 
 | |
|         ///////////////////////////////////////////////////////////////////////
 | |
|         //
 | |
|         //  rule_base class
 | |
|         //
 | |
|         //      The rule_base class implements the basic plumbing for rules
 | |
|         //      minus the storage mechanism. It is up to the derived class
 | |
|         //      to actually store the definition somewhere. The rule_base
 | |
|         //      class assumes that the derived class provides a get() function
 | |
|         //      that will return a pointer to a parser. The get() function
 | |
|         //      may return NULL. See rule below for details.
 | |
|         //
 | |
|         //      <<< For framework use only. Not for public consumption. >>>
 | |
|         //
 | |
|         ///////////////////////////////////////////////////////////////////////
 | |
|         template <
 | |
|             typename DerivedT       // derived class
 | |
|           , typename EmbedT         // how derived class is embedded
 | |
|           , typename T0 = nil_t     // see rule class
 | |
|           , typename T1 = nil_t     // see rule class
 | |
|           , typename T2 = nil_t     // see rule class
 | |
|         >
 | |
|         class rule_base; // forward declaration
 | |
| 
 | |
|         class rule_base_access
 | |
|         {
 | |
| #if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \
 | |
|     || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
 | |
|         public: // YUCK!
 | |
| #else
 | |
|             template <
 | |
|                 typename DerivedT
 | |
|               , typename EmbedT
 | |
|               , typename T0
 | |
|               , typename T1
 | |
|               , typename T2
 | |
|             >
 | |
|            friend class rule_base;
 | |
| #endif
 | |
|             template <typename RuleT>
 | |
|             static typename RuleT::abstract_parser_t*
 | |
|             get(RuleT const& r)
 | |
|             {
 | |
|                 return r.get();
 | |
|             }
 | |
|         };
 | |
| 
 | |
|         template <
 | |
|             typename DerivedT       // derived class
 | |
|           , typename EmbedT         // how derived class is embedded
 | |
|           , typename T0             // see rule class
 | |
|           , typename T1             // see rule class
 | |
|           , typename T2             // see rule class
 | |
|         >
 | |
|         class rule_base
 | |
|             : public parser<DerivedT>
 | |
|             , public impl::get_context<T0, T1, T2>::type::base_t
 | |
|             , public context_aux<
 | |
|                 typename impl::get_context<T0, T1, T2>::type, DerivedT>
 | |
|             , public impl::get_tag<T0, T1, T2>::type
 | |
|         {
 | |
|         public:
 | |
| 
 | |
|             typedef typename impl::get_scanner<T0, T1, T2>::type scanner_t;
 | |
|             typedef typename impl::get_context<T0, T1, T2>::type context_t;
 | |
|             typedef typename impl::get_tag<T0, T1, T2>::type tag_t;
 | |
| 
 | |
|             typedef EmbedT embed_t;
 | |
|             typedef typename context_t::context_linker_t linked_context_t;
 | |
|             typedef typename linked_context_t::attr_t attr_t;
 | |
| 
 | |
|             template <typename ScannerT>
 | |
|             struct result
 | |
|             {
 | |
|                 typedef typename match_result<ScannerT, attr_t>::type type;
 | |
|             };
 | |
| 
 | |
|             template <typename ScannerT>
 | |
|             typename parser_result<DerivedT, ScannerT>::type
 | |
|             parse(ScannerT const& scan) const
 | |
|             {
 | |
|                 typedef parser_scanner_linker<ScannerT> linked_scanner_t;
 | |
|                 typedef typename parser_result<DerivedT, ScannerT>::type result_t;
 | |
|                 BOOST_SPIRIT_CONTEXT_PARSE(
 | |
|                     scan, *this, linked_scanner_t, linked_context_t, result_t);
 | |
|             }
 | |
| 
 | |
|             template <typename ScannerT>
 | |
|             typename parser_result<DerivedT, ScannerT>::type
 | |
|             parse_main(ScannerT const& scan) const
 | |
|             {
 | |
|                 typename parser_result<DerivedT, ScannerT>::type hit;
 | |
| 
 | |
|                 //  MWCW 8.3 needs this cast to be done through a pointer,
 | |
|                 //  not a reference. Otherwise, it will silently construct
 | |
|                 //  a temporary, causing an infinite runtime recursion.
 | |
|                 DerivedT const* derived_this = static_cast<DerivedT const*>(this);
 | |
| 
 | |
|                 if (rule_base_access::get(*derived_this))
 | |
|                 {
 | |
|                     typename ScannerT::iterator_t s(scan.first);
 | |
|                     hit = rule_base_access::get(*derived_this)
 | |
|                             ->do_parse_virtual(scan);
 | |
|                     scan.group_match(hit, this->id(), s, scan.first);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     hit = scan.no_match();
 | |
|                 }
 | |
|                 return hit;
 | |
|             }
 | |
|         };
 | |
| 
 | |
|         ///////////////////////////////////////////////////////////////////////
 | |
|         //
 | |
|         //  abstract_parser class
 | |
|         //
 | |
|         ///////////////////////////////////////////////////////////////////////
 | |
|         template <typename ScannerT, typename AttrT>
 | |
|         struct abstract_parser
 | |
|         {
 | |
|             abstract_parser() {}
 | |
|             virtual ~abstract_parser() {}
 | |
| 
 | |
|             virtual typename match_result<ScannerT, AttrT>::type
 | |
|             do_parse_virtual(ScannerT const& scan) const = 0;
 | |
| 
 | |
|             virtual abstract_parser*
 | |
|             clone() const = 0;
 | |
|         };
 | |
| 
 | |
|         ///////////////////////////////////////////////////////////////////////
 | |
|         //
 | |
|         //  concrete_parser class
 | |
|         //
 | |
|         ///////////////////////////////////////////////////////////////////////
 | |
| #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
 | |
| #pragma warning(push)
 | |
| #pragma warning(disable:4512) //assignment operator could not be generated
 | |
| #endif
 | |
|         
 | |
|         template <typename ParserT, typename ScannerT, typename AttrT>
 | |
|         struct concrete_parser : abstract_parser<ScannerT, AttrT>
 | |
|         {
 | |
|             concrete_parser(ParserT const& p_) : p(p_) {}
 | |
|             virtual ~concrete_parser() {}
 | |
| 
 | |
|             virtual typename match_result<ScannerT, AttrT>::type
 | |
|             do_parse_virtual(ScannerT const& scan) const
 | |
|             {
 | |
|                 return p.parse(scan);
 | |
|             }
 | |
| 
 | |
|             virtual abstract_parser<ScannerT, AttrT>*
 | |
|             clone() const
 | |
|             {
 | |
|                 return new concrete_parser(p);
 | |
|             }
 | |
| 
 | |
|             typename ParserT::embed_t p;
 | |
|         };
 | |
|         
 | |
| #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
 | |
| #pragma warning(pop)
 | |
| #endif
 | |
| 
 | |
| #if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1
 | |
| 
 | |
|         ///////////////////////////////////////////////////////////////////////
 | |
|         //
 | |
|         //  This generates partial specializations for the class
 | |
|         //
 | |
|         //          abstract_parser
 | |
|         //
 | |
|         //  with an increasing number of different ScannerT template parameters
 | |
|         //  and corresponding do_parse_virtual function declarations for each
 | |
|         //  of the different required scanner types:
 | |
|         //
 | |
|         //      template <typename ScannerT0, ..., typename AttrT>
 | |
|         //      struct abstract_parser<scanner_list<ScannerT0, ...>, AttrT>
 | |
|         //      {
 | |
|         //          abstract_parser() {}
 | |
|         //          virtual ~abstract_parser() {}
 | |
|         //
 | |
|         //          virtual typename match_result<ScannerT0, AttrT>::type
 | |
|         //          do_parse_virtual(ScannerT0 const &scan) const = 0;
 | |
|         //
 | |
|         //          virtual abstract_parser*
 | |
|         //          clone() const = 0;
 | |
|         //
 | |
|         //          ...
 | |
|         //      };
 | |
|         //
 | |
|         ///////////////////////////////////////////////////////////////////////
 | |
|         #define BOOST_SPIRIT_RULE_ENUM_DOPARSE_A(z, N, _)                       \
 | |
|                 virtual typename match_result<                                  \
 | |
|                     BOOST_PP_CAT(ScannerT, N), AttrT                            \
 | |
|                 >::type                                                         \
 | |
|                 do_parse_virtual(                                               \
 | |
|                     BOOST_PP_CAT(ScannerT, N) const& scan) const = 0;           \
 | |
| 
 | |
|         #define BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS(z, N, _)                     \
 | |
|             template <                                                          \
 | |
|                 BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), typename ScannerT),  \
 | |
|                 typename AttrT                                                  \
 | |
|             >                                                                   \
 | |
|             struct abstract_parser<                                             \
 | |
|                 scanner_list<                                                   \
 | |
|                     BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT)        \
 | |
|                 >,                                                              \
 | |
|                 AttrT                                                           \
 | |
|             >                                                                   \
 | |
|             {                                                                   \
 | |
|                 abstract_parser() {}                                            \
 | |
|                 virtual ~abstract_parser() {}                                   \
 | |
|                                                                                 \
 | |
|                 BOOST_PP_REPEAT_ ## z(                                          \
 | |
|                     BOOST_PP_INC(N), BOOST_SPIRIT_RULE_ENUM_DOPARSE_A, _)       \
 | |
|                                                                                 \
 | |
|                 virtual abstract_parser*                                        \
 | |
|                 clone() const = 0;                                              \
 | |
|             };                                                                  \
 | |
| 
 | |
|         BOOST_PP_REPEAT_FROM_TO(1, BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT,
 | |
|             BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS, _)
 | |
| 
 | |
|         #undef BOOST_SPIRIT_RULE_ENUM_DOPARSE_A
 | |
|         #undef BOOST_SPIRIT_ENUM_ABSTRACT_PARSERS
 | |
|         ///////////////////////////////////////////////////////////////////////
 | |
| 
 | |
|         ///////////////////////////////////////////////////////////////////////
 | |
|         //
 | |
|         //  This generates partial specializations for the class
 | |
|         //
 | |
|         //          concrete_parser
 | |
|         //
 | |
|         //  with an increasing number of different ScannerT template parameters
 | |
|         //  and corresponding do_parse_virtual function declarations for each
 | |
|         //  of the different required scanner types:
 | |
|         //
 | |
|         //      template <
 | |
|         //          typename ParserT, typename ScannerT0, ..., typename AttrT
 | |
|         //      >
 | |
|         //      struct concrete_parser<
 | |
|         //          ParserT, scanner_list<ScannerT0, ...>, AttrT
 | |
|         //      >
 | |
|         //      :   public abstract_parser<scanner_list<ScannerT0, ...>, AttrT>
 | |
|         //      {
 | |
|         //          concrete_parser(ParserT const& p_) : p(p_) {}
 | |
|         //          virtual ~concrete_parser() {}
 | |
|         //
 | |
|         //          virtual typename match_result<ScannerT0, AttrT>::type
 | |
|         //          do_parse_virtual(ScannerT0 const &scan) const
 | |
|         //          { return p.parse(scan); }
 | |
|         //
 | |
|         //          virtual abstract_parser<scanner_list<ScannerT0, ...>, AttrT>*
 | |
|         //          clone() const
 | |
|         //          {
 | |
|         //              return new concrete_parser(p);
 | |
|         //          }
 | |
|         //
 | |
|         //          ...
 | |
|         //
 | |
|         //          typename ParserT::embed_t p;
 | |
|         //      };
 | |
|         //
 | |
|         ///////////////////////////////////////////////////////////////////////
 | |
|         #define BOOST_SPIRIT_RULE_ENUM_DOPARSE_C(z, N, _)                       \
 | |
|                 virtual typename match_result<                                  \
 | |
|                     BOOST_PP_CAT(ScannerT, N), AttrT                            \
 | |
|                 >::type                                                         \
 | |
|                 do_parse_virtual(                                               \
 | |
|                     BOOST_PP_CAT(ScannerT, N) const& scan) const                \
 | |
|                 { return p.parse(scan); }                                       \
 | |
| 
 | |
|         #define BOOST_SPIRIT_ENUM_CONCRETE_PARSERS(z, N, _)                     \
 | |
|             template <                                                          \
 | |
|                 typename ParserT,                                               \
 | |
|                 BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), typename ScannerT),  \
 | |
|                 typename AttrT                                                  \
 | |
|             >                                                                   \
 | |
|             struct concrete_parser<                                             \
 | |
|                 ParserT,                                                        \
 | |
|                 scanner_list<                                                   \
 | |
|                     BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT)        \
 | |
|                 >,                                                              \
 | |
|                 AttrT                                                           \
 | |
|             >                                                                   \
 | |
|             :   abstract_parser<                                                \
 | |
|                     scanner_list<                                               \
 | |
|                         BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT)    \
 | |
|                     >,                                                          \
 | |
|                     AttrT                                                       \
 | |
|                 >                                                               \
 | |
|             {                                                                   \
 | |
|                 concrete_parser(ParserT const& p_) : p(p_) {}                   \
 | |
|                 virtual ~concrete_parser() {}                                   \
 | |
|                                                                                 \
 | |
|                 BOOST_PP_REPEAT_ ## z(                                          \
 | |
|                     BOOST_PP_INC(N), BOOST_SPIRIT_RULE_ENUM_DOPARSE_C, _)       \
 | |
|                                                                                 \
 | |
|                 virtual abstract_parser<                                        \
 | |
|                     scanner_list<                                               \
 | |
|                         BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), ScannerT)    \
 | |
|                     >,                                                          \
 | |
|                     AttrT                                                       \
 | |
|                 >*                                                              \
 | |
|                 clone() const                                                   \
 | |
|                 {                                                               \
 | |
|                     return new concrete_parser(p);                              \
 | |
|                 }                                                               \
 | |
|                                                                                 \
 | |
|                 typename ParserT::embed_t p;                                    \
 | |
|             };                                                                  \
 | |
| 
 | |
|         BOOST_PP_REPEAT_FROM_TO(1, BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT,
 | |
|             BOOST_SPIRIT_ENUM_CONCRETE_PARSERS, _)
 | |
| 
 | |
|         #undef BOOST_SPIRIT_ENUM_CONCRETE_PARSERS
 | |
|         #undef BOOST_SPIRIT_RULE_ENUM_DOPARSE_C
 | |
|         ///////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| #endif // BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1
 | |
| 
 | |
|     } // namespace impl
 | |
| 
 | |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_END
 | |
| 
 | |
| }} // namespace boost::spirit
 | |
| 
 | |
| #endif
 | 
