]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/example/x3/rexpr/rexpr_min/rexpr.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / spirit / example / x3 / rexpr / rexpr_min / rexpr.cpp
1 /*=============================================================================
2 Copyright (c) 2001-2015 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 // A simple parser for X3 intended as a minimal starting point.
10 // 'rexpr' is a parser for a language resembling a minimal subset
11 // of json, but limited to a dictionary (composed of key=value pairs)
12 // where the value can itself be a string or a recursive dictionary.
13 //
14 // Example:
15 //
16 // {
17 // "color" = "blue"
18 // "size" = "29 cm."
19 // "position" = {
20 // "x" = "123"
21 // "y" = "456"
22 // }
23 // }
24 //
25 ///////////////////////////////////////////////////////////////////////////////
26
27 #include <boost/spirit/home/x3.hpp>
28 #include <boost/spirit/home/x3/support/ast/variant.hpp>
29 #include <boost/fusion/include/adapt_struct.hpp>
30 #include <boost/fusion/include/std_pair.hpp>
31 #include <boost/fusion/include/io.hpp>
32
33 #include <iostream>
34 #include <fstream>
35 #include <string>
36 #include <map>
37
38 ///////////////////////////////////////////////////////////////////////////////
39 // Our AST
40 ///////////////////////////////////////////////////////////////////////////////
41 namespace client { namespace ast
42 {
43 namespace fusion = boost::fusion;
44 namespace x3 = boost::spirit::x3;
45
46 struct rexpr;
47
48 struct rexpr_value : x3::variant<
49 std::string
50 , x3::forward_ast<rexpr>
51 >
52 {
53 using base_type::base_type;
54 using base_type::operator=;
55 };
56
57 typedef std::map<std::string, rexpr_value> rexpr_map;
58 typedef std::pair<std::string, rexpr_value> rexpr_key_value;
59
60 struct rexpr
61 {
62 rexpr_map entries;
63 };
64 }}
65
66 // We need to tell fusion about our rexpr struct
67 // to make it a first-class fusion citizen
68 BOOST_FUSION_ADAPT_STRUCT(client::ast::rexpr,
69 entries
70 )
71
72 ///////////////////////////////////////////////////////////////////////////////
73 // AST processing
74 ///////////////////////////////////////////////////////////////////////////////
75 namespace client { namespace ast
76 {
77 ///////////////////////////////////////////////////////////////////////////
78 // Print out the rexpr tree
79 ///////////////////////////////////////////////////////////////////////////
80 int const tabsize = 4;
81
82 struct rexpr_printer
83 {
84 typedef void result_type;
85
86 rexpr_printer(int indent = 0)
87 : indent(indent) {}
88
89 void operator()(rexpr const& ast) const
90 {
91 std::cout << '{' << std::endl;
92 for (auto const& entry : ast.entries)
93 {
94 tab(indent+tabsize);
95 std::cout << '"' << entry.first << "\" = ";
96 boost::apply_visitor(rexpr_printer(indent+tabsize), entry.second);
97 }
98 tab(indent);
99 std::cout << '}' << std::endl;
100 }
101
102 void operator()(std::string const& text) const
103 {
104 std::cout << '"' << text << '"' << std::endl;
105 }
106
107 void tab(int spaces) const
108 {
109 for (int i = 0; i < spaces; ++i)
110 std::cout << ' ';
111 }
112
113 int indent;
114 };
115 }}
116
117 ///////////////////////////////////////////////////////////////////////////////
118 // Our rexpr grammar
119 ///////////////////////////////////////////////////////////////////////////////
120 namespace client { namespace parser
121 {
122 namespace x3 = boost::spirit::x3;
123 namespace ascii = boost::spirit::x3::ascii;
124
125 using x3::lit;
126 using x3::lexeme;
127
128 using ascii::char_;
129 using ascii::string;
130
131 x3::rule<class rexpr_value, ast::rexpr_value>
132 rexpr_value = "rexpr_value";
133
134 x3::rule<class rexpr, ast::rexpr>
135 rexpr = "rexpr";
136
137 x3::rule<class rexpr_key_value, ast::rexpr_key_value>
138 rexpr_key_value = "rexpr_key_value";
139
140 auto const quoted_string =
141 lexeme['"' >> *(char_ - '"') >> '"'];
142
143 auto const rexpr_value_def =
144 quoted_string | rexpr;
145
146 auto const rexpr_key_value_def =
147 quoted_string >> '=' >> rexpr_value;
148
149 auto const rexpr_def =
150 '{' >> *rexpr_key_value >> '}';
151
152 BOOST_SPIRIT_DEFINE(rexpr_value, rexpr, rexpr_key_value);
153 }}
154
155 ///////////////////////////////////////////////////////////////////////////////
156 // Main program
157 ///////////////////////////////////////////////////////////////////////////////
158 int main(int argc, char **argv)
159 {
160 char const* filename;
161 if (argc > 1)
162 {
163 filename = argv[1];
164 }
165 else
166 {
167 std::cerr << "Error: No input file provided." << std::endl;
168 return 1;
169 }
170
171 std::ifstream in(filename, std::ios_base::in);
172
173 if (!in)
174 {
175 std::cerr << "Error: Could not open input file: "
176 << filename << std::endl;
177 return 1;
178 }
179
180 std::string storage; // We will read the contents here.
181 in.unsetf(std::ios::skipws); // No white space skipping!
182 std::copy(
183 std::istream_iterator<char>(in),
184 std::istream_iterator<char>(),
185 std::back_inserter(storage));
186
187 using client::parser::rexpr; // Our grammar
188 client::ast::rexpr ast; // Our tree
189
190 using boost::spirit::x3::ascii::space;
191 std::string::const_iterator iter = storage.begin();
192 std::string::const_iterator end = storage.end();
193 bool r = phrase_parse(iter, end, rexpr, space, ast);
194
195 if (r && iter == end)
196 {
197 std::cout << "-------------------------\n";
198 std::cout << "Parsing succeeded\n";
199 std::cout << "-------------------------\n";
200 client::ast::rexpr_printer printer;
201 printer(ast);
202 return 0;
203 }
204 else
205 {
206 std::string::const_iterator some = iter+30;
207 std::string context(iter, (some>end)?end:some);
208 std::cout << "-------------------------\n";
209 std::cout << "Parsing failed\n";
210 std::cout << "stopped at: \": " << context << "...\"\n";
211 std::cout << "-------------------------\n";
212 return 1;
213 }
214 }