]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/workbench/x3/toy/toy.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / spirit / workbench / x3 / toy / toy.cpp
1 #include <iostream>
2 #include <utility>
3 #include <cstring>
4 #include <boost/mpl/identity.hpp>
5
6 namespace boost { namespace spirit { namespace x3
7 {
8 template <typename Derived>
9 struct parser
10 {
11 Derived const& derived() const
12 {
13 return *static_cast<Derived const*>(this);
14 }
15 };
16
17 template <typename Char>
18 struct char_parser : parser<char_parser<Char>>
19 {
20 char_parser(Char ch) : ch(ch) {}
21
22 template <typename Iterator, typename Context>
23 bool parse(Iterator& first, Iterator last, Context const& ctx) const
24 {
25 if (first != last && *first == ch)
26 {
27 ++first;
28 return true;
29 }
30 return false;
31 }
32
33 Char ch;
34 };
35
36 template <typename Char>
37 inline char_parser<Char> char_(Char ch)
38 {
39 return char_parser<Char>(ch);
40 };
41
42 template <typename Left, typename Right>
43 struct sequence_parser : parser<sequence_parser<Left, Right>>
44 {
45 sequence_parser(Left left, Right right)
46 : left(left), right(right) {}
47
48 template <typename Iterator, typename Context>
49 bool parse(Iterator& first, Iterator last, Context const& ctx) const
50 {
51 return left.parse(first, last, ctx)
52 && right.parse(first, last, ctx);
53 }
54
55 Left left;
56 Right right;
57 };
58
59 template <typename Left, typename Right>
60 inline sequence_parser<Left, Right> operator>>(
61 parser<Left> const& left, parser<Right> const& right)
62 {
63 return sequence_parser<Left, Right>(
64 left.derived(), right.derived());
65 }
66
67 template <typename Left, typename Right>
68 struct alternative_parser : parser<alternative_parser<Left, Right>>
69 {
70 alternative_parser(Left left, Right right)
71 : left(left), right(right) {}
72
73 template <typename Iterator, typename Context>
74 bool parse(Iterator& first, Iterator last, Context const& ctx) const
75 {
76 if (left.parse(first, last, ctx))
77 return true;
78 return right.parse(first, last, ctx);
79 }
80
81 Left left;
82 Right right;
83 };
84
85 template <typename Left, typename Right>
86 inline alternative_parser<Left, Right> operator|(
87 parser<Left> const& left, parser<Right> const& right)
88 {
89 return alternative_parser<Left, Right>(
90 left.derived(), right.derived());
91 }
92
93 template <typename ID, typename T, typename NextContext>
94 struct context
95 {
96 context(T const& val, NextContext const& next_ctx)
97 : val(val), next_ctx(next_ctx) {}
98
99 T const& get(mpl::identity<ID>) const
100 {
101 return val;
102 }
103
104 template <typename Identity>
105 decltype(std::declval<NextContext>().get(Identity()))
106 get(Identity id) const
107 {
108 return next_ctx.get(id);
109 }
110
111 T const& val;
112 NextContext const& next_ctx;
113 };
114
115 struct empty_context
116 {
117 struct undefined {};
118 template <typename ID>
119 undefined get(ID) const
120 {
121 return undefined();
122 }
123 };
124
125 template <typename ID, typename RHS>
126 struct rule_definition : parser<rule_definition<ID, RHS>>
127 {
128 rule_definition(RHS rhs)
129 : rhs(rhs) {}
130
131 template <typename Iterator, typename Context>
132 bool parse(Iterator& first, Iterator last, Context const& ctx) const
133 {
134 context<ID, RHS, Context> this_ctx(rhs, ctx);
135 return rhs.parse(first, last, this_ctx);
136 }
137
138 RHS rhs;
139 };
140
141 template <typename ID>
142 struct rule : parser<rule<ID>>
143 {
144 template <typename Derived>
145 rule_definition<ID, Derived>
146 operator=(parser<Derived> const& definition) const
147 {
148 return rule_definition<ID, Derived>(definition.derived());
149 }
150
151 template <typename Iterator, typename Context>
152 bool parse(Iterator& first, Iterator last, Context const& ctx) const
153 {
154 return ctx.get(mpl::identity<ID>()).parse(first, last, ctx);
155 }
156 };
157
158 template <typename Iterator, typename Derived>
159 inline bool parse(parser<Derived> const& p, Iterator& first, Iterator last)
160 {
161 empty_context ctx;
162 return p.derived().parse(first, last, ctx);
163 }
164
165 }}}
166
167 ///////////////////////////////////////////////////////////////////////////////
168 // test code
169
170 template <typename Parser>
171 bool test_parse(Parser const& p, char const* in)
172 {
173 return parse(p, in, in + std::strlen(in));
174 }
175
176 namespace parser
177 {
178 using namespace boost::spirit::x3;
179
180 namespace g_definition
181 {
182 auto const x = rule<class x>();
183 auto const ax = char_('a') >> x;
184
185 auto const g =
186 x = char_('x') | ax;
187 }
188 using g_definition::g;
189 }
190
191 int main()
192 {
193
194 { // a non-recursive parser
195 using namespace boost::spirit::x3;
196
197 auto abc = char_('a') >> char_('b') >> char_('c');
198 std::cout << test_parse(abc, "abc") << std::endl;
199 std::cout << test_parse(abc, "abx") << std::endl;
200 std::cout << "==========================================" << std::endl;
201 }
202
203 { // a recursive rule
204 using namespace boost::spirit::x3;
205
206 auto const x = rule<class x>();
207 auto const ax = char_('a') >> x;
208 auto const start = (x = char_('x') | ax);
209
210 std::cout << test_parse(start, "x") << std::endl;
211 std::cout << test_parse(start, "ax") << std::endl;
212 std::cout << test_parse(start, "aaaaax") << std::endl;
213 std::cout << test_parse(start, "aaz") << std::endl;
214 std::cout << "==========================================" << std::endl;
215 }
216
217 { // a grammar ( gcc and clang only: see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3582.html )
218
219 using namespace boost::spirit::x3;
220 auto g = []()
221 {
222 rule<class x> x;
223 auto ax = char_('a') >> x;
224 return x = char_('x') | ax;
225
226 }();
227
228 std::cout << test_parse(g, "x") << std::endl;
229 std::cout << test_parse(g, "ax") << std::endl;
230 std::cout << test_parse(g, "aaaaax") << std::endl;
231 std::cout << test_parse(g, "aaz") << std::endl;
232 std::cout << "==========================================" << std::endl;
233 }
234
235 { // another grammar using namespaces (standard c++, see grammar g definition above in namespace parser.)
236 using parser::g;
237
238 std::cout << test_parse(g, "x") << std::endl;
239 std::cout << test_parse(g, "ax") << std::endl;
240 std::cout << test_parse(g, "aaaaax") << std::endl;
241 std::cout << test_parse(g, "aaz") << std::endl;
242 std::cout << "==========================================" << std::endl;
243 }
244
245 return 0;
246 }
247