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