]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Copyright (c) 2001-2014 Joel de Guzman | |
3 | ||
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_X3_RULE_JAN_08_2012_0326PM) | |
8 | #define BOOST_SPIRIT_X3_RULE_JAN_08_2012_0326PM | |
9 | ||
10 | #include <boost/spirit/home/x3/nonterminal/detail/rule.hpp> | |
11 | #include <boost/type_traits/is_same.hpp> | |
12 | #include <boost/spirit/home/x3/support/context.hpp> | |
13 | #include <boost/preprocessor/variadic/to_seq.hpp> | |
14 | #include <boost/preprocessor/variadic/elem.hpp> | |
15 | #include <boost/preprocessor/seq/for_each.hpp> | |
16 | ||
17 | #if !defined(BOOST_SPIRIT_X3_NO_RTTI) | |
18 | #include <typeinfo> | |
19 | #endif | |
20 | ||
21 | namespace boost { namespace spirit { namespace x3 | |
22 | { | |
23 | template <typename ID> | |
24 | struct identity {}; | |
25 | ||
26 | // default parse_rule implementation | |
27 | template <typename ID, typename Attribute, typename Iterator | |
28 | , typename Context, typename ActualAttribute> | |
29 | inline detail::default_parse_rule_result | |
30 | parse_rule( | |
31 | rule<ID, Attribute> rule_ | |
32 | , Iterator& first, Iterator const& last | |
33 | , Context const& context, ActualAttribute& attr) | |
34 | { | |
35 | static_assert(!is_same<decltype(get<ID>(context)), unused_type>::value, | |
36 | "BOOST_SPIRIT_DEFINE undefined for this rule."); | |
37 | return get<ID>(context).parse(first, last, context, unused, attr); | |
38 | } | |
39 | ||
40 | template <typename ID, typename RHS, typename Attribute, bool force_attribute_> | |
41 | struct rule_definition : parser<rule_definition<ID, RHS, Attribute, force_attribute_>> | |
42 | { | |
43 | typedef rule_definition<ID, RHS, Attribute, force_attribute_> this_type; | |
44 | typedef ID id; | |
45 | typedef RHS rhs_type; | |
46 | typedef rule<ID, Attribute> lhs_type; | |
47 | typedef Attribute attribute_type; | |
48 | ||
49 | static bool const has_attribute = | |
50 | !is_same<Attribute, unused_type>::value; | |
51 | static bool const handles_container = | |
52 | traits::is_container<Attribute>::value; | |
53 | static bool const force_attribute = | |
54 | force_attribute_; | |
55 | ||
56 | rule_definition(RHS const& rhs, char const* name) | |
57 | : rhs(rhs), name(name) {} | |
58 | ||
59 | template <typename Iterator, typename Context, typename Attribute_> | |
60 | bool parse(Iterator& first, Iterator const& last | |
61 | , Context const& context, unused_type, Attribute_& attr) const | |
62 | { | |
63 | return detail::rule_parser<attribute_type, ID> | |
64 | ::call_rule_definition( | |
65 | rhs, name, first, last | |
66 | , context | |
67 | , attr | |
68 | , mpl::bool_<force_attribute>()); | |
69 | } | |
70 | ||
71 | RHS rhs; | |
72 | char const* name; | |
73 | }; | |
74 | ||
75 | template <typename ID, typename Attribute, bool force_attribute_> | |
76 | struct rule : parser<rule<ID, Attribute>> | |
77 | { | |
78 | typedef ID id; | |
79 | typedef Attribute attribute_type; | |
80 | static bool const has_attribute = | |
81 | !is_same<Attribute, unused_type>::value; | |
82 | static bool const handles_container = | |
83 | traits::is_container<Attribute>::value; | |
84 | static bool const force_attribute = force_attribute_; | |
85 | ||
86 | #if !defined(BOOST_SPIRIT_X3_NO_RTTI) | |
87 | rule() : name(typeid(rule).name()) {} | |
88 | #else | |
89 | rule() : name("unnamed") {} | |
90 | #endif | |
91 | ||
92 | rule(char const* name) | |
93 | : name(name) {} | |
94 | ||
95 | template <typename RHS> | |
96 | rule_definition< | |
97 | ID, typename extension::as_parser<RHS>::value_type, Attribute, force_attribute_> | |
98 | operator=(RHS const& rhs) const | |
99 | { | |
100 | return { as_parser(rhs), name }; | |
101 | } | |
102 | ||
103 | template <typename RHS> | |
104 | rule_definition< | |
105 | ID, typename extension::as_parser<RHS>::value_type, Attribute, true> | |
106 | operator%=(RHS const& rhs) const | |
107 | { | |
108 | return { as_parser(rhs), name }; | |
109 | } | |
110 | ||
111 | ||
112 | template <typename Iterator, typename Context, typename Attribute_> | |
113 | bool parse(Iterator& first, Iterator const& last | |
114 | , Context const& context, unused_type, Attribute_& attr) const | |
115 | { | |
116 | return parse_rule(*this, first, last, context, attr); | |
117 | } | |
118 | ||
119 | char const* name; | |
120 | }; | |
121 | ||
122 | namespace traits | |
123 | { | |
124 | template <typename T, typename Enable = void> | |
125 | struct is_rule : mpl::false_ {}; | |
126 | ||
127 | template <typename ID, typename Attribute> | |
128 | struct is_rule<rule<ID, Attribute>> : mpl::true_ {}; | |
129 | ||
130 | template <typename ID, typename Attribute, typename RHS, bool force_attribute> | |
131 | struct is_rule<rule_definition<ID, RHS, Attribute, force_attribute>> : mpl::true_ {}; | |
132 | } | |
133 | ||
134 | template <typename T> | |
135 | struct get_info<T, typename enable_if<traits::is_rule<T>>::type> | |
136 | { | |
137 | typedef std::string result_type; | |
138 | std::string operator()(T const& r) const | |
139 | { | |
140 | return r.name; | |
141 | } | |
142 | }; | |
143 | ||
144 | #define BOOST_SPIRIT_DECLARE_(r, data, rule_type) \ | |
145 | template <typename Iterator, typename Context, typename Attribute> \ | |
146 | bool parse_rule( \ | |
147 | rule_type rule_ \ | |
148 | , Iterator& first, Iterator const& last \ | |
149 | , Context const& context, Attribute& attr); \ | |
150 | /***/ | |
151 | ||
152 | #define BOOST_SPIRIT_DECLARE(...) BOOST_PP_SEQ_FOR_EACH( \ | |
153 | BOOST_SPIRIT_DECLARE_, _, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \ | |
154 | /***/ | |
155 | ||
156 | #define BOOST_SPIRIT_DEFINE_(r, data, rule_name) \ | |
157 | template <typename Iterator, typename Context, typename Attribute> \ | |
158 | inline bool parse_rule( \ | |
159 | decltype(rule_name) rule_ \ | |
160 | , Iterator& first, Iterator const& last \ | |
161 | , Context const& context, Attribute& attr) \ | |
162 | { \ | |
163 | using boost::spirit::x3::unused; \ | |
164 | static auto const def_ = (rule_name = BOOST_PP_CAT(rule_name, _def)); \ | |
165 | return def_.parse(first, last, context, unused, attr); \ | |
166 | } \ | |
167 | /***/ | |
168 | ||
169 | #define BOOST_SPIRIT_DEFINE(...) BOOST_PP_SEQ_FOR_EACH( \ | |
170 | BOOST_SPIRIT_DEFINE_, _, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \ | |
171 | /***/ | |
172 | ||
173 | #define BOOST_SPIRIT_INSTANTIATE(rule_type, Iterator, Context) \ | |
174 | template bool parse_rule<Iterator, Context, rule_type::attribute_type>( \ | |
175 | rule_type rule_ \ | |
176 | , Iterator& first, Iterator const& last \ | |
177 | , Context const& context, rule_type::attribute_type& attr); \ | |
178 | /***/ | |
179 | ||
180 | ||
181 | }}} | |
182 | ||
183 | #endif |