rule.hpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*=============================================================================
  2. Copyright (c) 1998-2003 Joel de Guzman
  3. http://spirit.sourceforge.net/
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. =============================================================================*/
  7. #if !defined(BOOST_SPIRIT_RULE_HPP)
  8. #define BOOST_SPIRIT_RULE_HPP
  9. #include <boost/static_assert.hpp>
  10. ///////////////////////////////////////////////////////////////////////////////
  11. //
  12. // Spirit predefined maximum number of simultaneously usable different
  13. // scanner types.
  14. //
  15. // This limit defines the maximum number of possible different scanner
  16. // types for which a specific rule<> may be used. If this isn't defined, a
  17. // rule<> may be used with one scanner type only (multiple scanner support
  18. // is disabled).
  19. //
  20. ///////////////////////////////////////////////////////////////////////////////
  21. #if !defined(BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT)
  22. # define BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT 1
  23. #endif
  24. // Ensure a meaningful maximum number of simultaneously usable scanner types
  25. BOOST_STATIC_ASSERT(BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 0);
  26. #include <boost/scoped_ptr.hpp>
  27. #include <boost/spirit/home/classic/namespace.hpp>
  28. #include <boost/spirit/home/classic/core/non_terminal/impl/rule.ipp>
  29. #if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1
  30. # include <boost/preprocessor/enum_params.hpp>
  31. #endif
  32. ///////////////////////////////////////////////////////////////////////////////
  33. namespace boost { namespace spirit {
  34. BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
  35. #if BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT > 1
  36. ///////////////////////////////////////////////////////////////////////////
  37. //
  38. // scanner_list (a fake scanner)
  39. //
  40. // Typically, rules are tied to a specific scanner type and
  41. // a particular rule cannot be used with anything else. Sometimes
  42. // there's a need for rules that can accept more than one scanner
  43. // type. The scanner_list<S0, ...SN> can be used as a template
  44. // parameter to the rule class to specify up to the number of
  45. // scanner types defined by the BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT
  46. // constant. Example:
  47. //
  48. // rule<scanner_list<ScannerT0, ScannerT1> > r;
  49. //
  50. // *** This feature is available only to compilers that support
  51. // partial template specialization. ***
  52. //
  53. ///////////////////////////////////////////////////////////////////////////
  54. template <
  55. BOOST_PP_ENUM_PARAMS(
  56. BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT,
  57. typename ScannerT
  58. )
  59. >
  60. struct scanner_list : scanner_base {};
  61. #endif
  62. ///////////////////////////////////////////////////////////////////////////
  63. //
  64. // rule class
  65. //
  66. // The rule is a polymorphic parser that acts as a named place-
  67. // holder capturing the behavior of an EBNF expression assigned to
  68. // it.
  69. //
  70. // The rule is a template class parameterized by:
  71. //
  72. // 1) scanner (scanner_t, see scanner.hpp),
  73. // 2) the rule's context (context_t, see parser_context.hpp)
  74. // 3) an arbitrary tag (tag_t, see parser_id.hpp) that allows
  75. // a rule to be tagged for identification.
  76. //
  77. // These template parameters may be specified in any order. The
  78. // scanner will default to scanner<> when it is not specified.
  79. // The context will default to parser_context when not specified.
  80. // The tag will default to parser_address_tag when not specified.
  81. //
  82. // The definition of the rule (its right hand side, RHS) held by
  83. // the rule through a scoped_ptr. When a rule is seen in the RHS
  84. // of an assignment or copy construction EBNF expression, the rule
  85. // is held by the LHS rule by reference.
  86. //
  87. ///////////////////////////////////////////////////////////////////////////
  88. template <
  89. typename T0 = nil_t
  90. , typename T1 = nil_t
  91. , typename T2 = nil_t
  92. >
  93. class rule
  94. : public impl::rule_base<
  95. rule<T0, T1, T2>
  96. , rule<T0, T1, T2> const&
  97. , T0, T1, T2>
  98. {
  99. public:
  100. typedef rule<T0, T1, T2> self_t;
  101. typedef impl::rule_base<
  102. self_t
  103. , self_t const&
  104. , T0, T1, T2>
  105. base_t;
  106. typedef typename base_t::scanner_t scanner_t;
  107. typedef typename base_t::attr_t attr_t;
  108. typedef impl::abstract_parser<scanner_t, attr_t> abstract_parser_t;
  109. rule() : ptr() {}
  110. ~rule() {}
  111. rule(rule const& r)
  112. : ptr(new impl::concrete_parser<rule, scanner_t, attr_t>(r)) {}
  113. template <typename ParserT>
  114. rule(ParserT const& p)
  115. : ptr(new impl::concrete_parser<ParserT, scanner_t, attr_t>(p)) {}
  116. template <typename ParserT>
  117. rule& operator=(ParserT const& p)
  118. {
  119. ptr.reset(new impl::concrete_parser<ParserT, scanner_t, attr_t>(p));
  120. return *this;
  121. }
  122. rule& operator=(rule const& r)
  123. {
  124. ptr.reset(new impl::concrete_parser<rule, scanner_t, attr_t>(r));
  125. return *this;
  126. }
  127. rule<T0, T1, T2>
  128. copy() const
  129. {
  130. return rule<T0, T1, T2>(ptr.get() ? ptr->clone() : 0);
  131. }
  132. private:
  133. friend class impl::rule_base_access;
  134. abstract_parser_t*
  135. get() const
  136. {
  137. return ptr.get();
  138. }
  139. rule(abstract_parser_t* ptr_)
  140. : ptr(ptr_) {}
  141. rule(abstract_parser_t const* ptr_)
  142. : ptr(ptr_) {}
  143. scoped_ptr<abstract_parser_t> ptr;
  144. };
  145. BOOST_SPIRIT_CLASSIC_NAMESPACE_END
  146. }} // namespace BOOST_SPIRIT_CLASSIC_NS
  147. #endif