]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/example/x3/annotation.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / spirit / example / x3 / annotation.cpp
1 /*=============================================================================
2 Copyright (c) 2002-2018 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 ///////////////////////////////////////////////////////////////////////////////
8 //
9 // Based on the employee parser (see employee.cpp), this example shows how
10 // to annotate the AST with the iterator positions for access to the source
11 // code when post processing. This example also shows how to "inject" client
12 // data, using the "with" directive, that the handlers can access.
13 //
14 // [ JDG May 9, 2007 ]
15 // [ JDG May 13, 2015 ] spirit X3
16 // [ JDG Feb 22, 2018 ] Parser annotations for spirit X3
17 //
18 // I would like to thank Rainbowverse, llc (https://primeorbial.com/)
19 // for sponsoring this work and donating it to the community.
20 //
21 ///////////////////////////////////////////////////////////////////////////////
22
23 #include <boost/spirit/home/x3.hpp>
24 #include <boost/spirit/home/x3/support/ast/position_tagged.hpp>
25 #include <boost/fusion/include/adapt_struct.hpp>
26 #include <boost/fusion/include/io.hpp>
27
28 #include <iostream>
29 #include <string>
30
31 namespace client { namespace ast
32 {
33 ///////////////////////////////////////////////////////////////////////////
34 // Our AST (employee and person structs)
35 ///////////////////////////////////////////////////////////////////////////
36 namespace x3 = boost::spirit::x3;
37
38 struct person : x3::position_tagged
39 {
40 person(
41 std::string const& first_name = ""
42 , std::string const& last_name = ""
43 )
44 : first_name(first_name)
45 , last_name(last_name)
46 {}
47
48 std::string first_name, last_name;
49 };
50
51 struct employee : x3::position_tagged
52 {
53 int age;
54 person who;
55 double salary;
56 };
57
58 using boost::fusion::operator<<;
59 }}
60
61 // We need to tell fusion about our employee struct
62 // to make it a first-class fusion citizen. This has to
63 // be in global scope.
64
65 BOOST_FUSION_ADAPT_STRUCT(client::ast::person,
66 first_name, last_name
67 )
68
69 BOOST_FUSION_ADAPT_STRUCT(client::ast::employee,
70 age, who, salary
71 )
72
73 namespace client
74 {
75 namespace parser
76 {
77 namespace x3 = boost::spirit::x3;
78 namespace ascii = boost::spirit::x3::ascii;
79
80 ///////////////////////////////////////////////////////////////////////
81 // Our annotation handler
82 ///////////////////////////////////////////////////////////////////////
83
84 // tag used to get the position cache from the context
85 struct position_cache_tag;
86
87 struct annotate_position
88 {
89 template <typename T, typename Iterator, typename Context>
90 inline void on_success(Iterator const& first, Iterator const& last
91 , T& ast, Context const& context)
92 {
93 auto& position_cache = x3::get<position_cache_tag>(context).get();
94 position_cache.annotate(ast, first, last);
95 }
96 };
97
98 ///////////////////////////////////////////////////////////////////////
99 // Our employee parser
100 ///////////////////////////////////////////////////////////////////////
101
102 using x3::int_;
103 using x3::double_;
104 using x3::lexeme;
105 using ascii::char_;
106
107 struct quoted_string_class;
108 struct person_class;
109 struct employee_class;
110
111 x3::rule<quoted_string_class, std::string> const quoted_string = "quoted_string";
112 x3::rule<person_class, ast::person> const person = "person";
113 x3::rule<employee_class, ast::employee> const employee = "employee";
114
115 auto const quoted_string_def = lexeme['"' >> +(char_ - '"') >> '"'];
116 auto const person_def = quoted_string >> ',' >> quoted_string;
117
118 auto const employee_def =
119 '{'
120 >> int_ >> ','
121 >> person >> ','
122 >> double_
123 >> '}'
124 ;
125
126 auto const employees = employee >> *(',' >> employee);
127
128 BOOST_SPIRIT_DEFINE(quoted_string, person, employee);
129
130 struct quoted_string_class {};
131 struct person_class : annotate_position {};
132 struct employee_class : annotate_position {};
133 }
134 }
135
136 ///////////////////////////////////////////////////////////////////////////////
137 // Main program
138 ///////////////////////////////////////////////////////////////////////////////
139
140 ///////////////////////////////////////////////////////////////////////////////
141 // Our main parse entry point
142 ///////////////////////////////////////////////////////////////////////////////
143
144 using iterator_type = std::string::const_iterator;
145 using position_cache = boost::spirit::x3::position_cache<std::vector<iterator_type>>;
146
147 std::vector<client::ast::employee>
148 parse(std::string const& input, position_cache& positions)
149 {
150 using boost::spirit::x3::ascii::space;
151
152 std::vector<client::ast::employee> ast;
153 iterator_type iter = input.begin();
154 iterator_type const end = input.end();
155
156 using boost::spirit::x3::with;
157
158 // Our parser
159 using client::parser::employees;
160 using client::parser::position_cache_tag;
161
162 auto const parser =
163 // we pass our position_cache to the parser so we can access
164 // it later in our on_sucess handlers
165 with<position_cache_tag>(std::ref(positions))
166 [
167 employees
168 ];
169
170 bool r = phrase_parse(iter, end, parser, space, ast);
171
172 if (r && iter == end)
173 {
174 std::cout << boost::fusion::tuple_open('[');
175 std::cout << boost::fusion::tuple_close(']');
176 std::cout << boost::fusion::tuple_delimiter(", ");
177
178 std::cout << "-------------------------\n";
179 std::cout << "Parsing succeeded\n";
180
181 for (auto const& emp : ast)
182 {
183 std::cout << "got: " << emp << std::endl;
184 }
185 std::cout << "\n-------------------------\n";
186
187 }
188 else
189 {
190 std::cout << "-------------------------\n";
191 std::cout << "Parsing failed\n";
192 std::cout << "-------------------------\n";
193 ast.clear();
194 }
195 return ast;
196 }
197
198 // Sample input:
199
200 std::string input = R"(
201 {
202 23,
203 "Amanda",
204 "Stefanski",
205 1000.99
206 },
207 {
208 35,
209 "Angie",
210 "Chilcote",
211 2000.99
212 },
213 {
214 43,
215 "Dannie",
216 "Dillinger",
217 3000.99
218 },
219 {
220 22,
221 "Dorene",
222 "Dole",
223 2500.99
224 },
225 {
226 38,
227 "Rossana",
228 "Rafferty",
229 5000.99
230 }
231 )";
232
233 int
234 main()
235 {
236 position_cache positions{input.begin(), input.end()};
237 auto ast = parse(input, positions);
238
239 // Get the source of the 2nd employee and print it
240 auto pos = positions.position_of(ast[1]); // zero based of course!
241 std::cout << "Here's the 2nd employee:" << std::endl;
242 std::cout << std::string(pos.begin(), pos.end()) << std::endl;
243 std::cout << "-------------------------\n";
244 return 0;
245 }