]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/example/x3/annotation.cpp
1 /*=============================================================================
2 Copyright (c) 2002-2018 Joel de Guzman
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 ///////////////////////////////////////////////////////////////////////////////
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.
14 // [ JDG May 9, 2007 ]
15 // [ JDG May 13, 2015 ] spirit X3
16 // [ JDG Feb 22, 2018 ] Parser annotations for spirit X3
18 // I would like to thank Rainbowverse, llc (https://primeorbial.com/)
19 // for sponsoring this work and donating it to the community.
21 ///////////////////////////////////////////////////////////////////////////////
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>
31 namespace client
{ namespace ast
33 ///////////////////////////////////////////////////////////////////////////
34 // Our AST (employee and person structs)
35 ///////////////////////////////////////////////////////////////////////////
36 namespace x3
= boost::spirit::x3
;
38 struct person
: x3::position_tagged
41 std::string
const& first_name
= ""
42 , std::string
const& last_name
= ""
44 : first_name(first_name
)
45 , last_name(last_name
)
48 std::string first_name
, last_name
;
51 struct employee
: x3::position_tagged
58 using boost::fusion::operator<<;
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.
65 BOOST_FUSION_ADAPT_STRUCT(client::ast::person
,
69 BOOST_FUSION_ADAPT_STRUCT(client::ast::employee
,
77 namespace x3
= boost::spirit::x3
;
78 namespace ascii
= boost::spirit::x3::ascii
;
80 ///////////////////////////////////////////////////////////////////////
81 // Our annotation handler
82 ///////////////////////////////////////////////////////////////////////
84 // tag used to get the position cache from the context
85 struct position_cache_tag
;
87 struct annotate_position
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
)
93 auto& position_cache
= x3::get
<position_cache_tag
>(context
).get();
94 position_cache
.annotate(ast
, first
, last
);
98 ///////////////////////////////////////////////////////////////////////
99 // Our employee parser
100 ///////////////////////////////////////////////////////////////////////
107 struct quoted_string_class
;
109 struct employee_class
;
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";
115 auto const quoted_string_def
= lexeme
['"' >> +(char_
- '"') >> '"'];
116 auto const person_def
= quoted_string
>> ',' >> quoted_string
;
118 auto const employee_def
=
126 auto const employees
= employee
>> *(',' >> employee
);
128 BOOST_SPIRIT_DEFINE(quoted_string
, person
, employee
);
130 struct quoted_string_class
{};
131 struct person_class
: annotate_position
{};
132 struct employee_class
: annotate_position
{};
136 ///////////////////////////////////////////////////////////////////////////////
138 ///////////////////////////////////////////////////////////////////////////////
140 ///////////////////////////////////////////////////////////////////////////////
141 // Our main parse entry point
142 ///////////////////////////////////////////////////////////////////////////////
144 using iterator_type
= std::string::const_iterator
;
145 using position_cache
= boost::spirit::x3::position_cache
<std::vector
<iterator_type
>>;
147 std::vector
<client::ast::employee
>
148 parse(std::string
const& input
, position_cache
& positions
)
150 using boost::spirit::x3::ascii::space
;
152 std::vector
<client::ast::employee
> ast
;
153 iterator_type iter
= input
.begin();
154 iterator_type
const end
= input
.end();
156 using boost::spirit::x3::with
;
159 using client::parser::employees
;
160 using client::parser::position_cache_tag
;
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
))
170 bool r
= phrase_parse(iter
, end
, parser
, space
, ast
);
172 if (r
&& iter
== end
)
174 std::cout
<< boost::fusion::tuple_open('[');
175 std::cout
<< boost::fusion::tuple_close(']');
176 std::cout
<< boost::fusion::tuple_delimiter(", ");
178 std::cout
<< "-------------------------\n";
179 std::cout
<< "Parsing succeeded\n";
181 for (auto const& emp
: ast
)
183 std::cout
<< "got: " << emp
<< std::endl
;
185 std::cout
<< "\n-------------------------\n";
190 std::cout
<< "-------------------------\n";
191 std::cout
<< "Parsing failed\n";
192 std::cout
<< "-------------------------\n";
200 std::string input
= R
"(
236 position_cache positions
{input
.begin(), input
.end()};
237 auto ast
= parse(input
, positions
);
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";