]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/example/x3/calc/calc4c/grammar.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / spirit / example / x3 / calc / calc4c / grammar.hpp
1 /*=============================================================================
2 Copyright (c) 2001-2014 Joel de Guzman
3 Copyright (c) 2013-2014 Agustin Berge
4
5 Distributed under the Boost Software License, Version 1.0. (See accompanying
6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 =============================================================================*/
8 ///////////////////////////////////////////////////////////////////////////////
9 //
10 // A Calculator example demonstrating generation of AST. The AST,
11 // once created, is traversed, 1) To print its contents and
12 // 2) To evaluate the result.
13 //
14 // [ JDG April 28, 2008 ] For BoostCon 2008
15 // [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
16 // [ JDG January 9, 2013 ] Spirit X3
17 //
18 ///////////////////////////////////////////////////////////////////////////////
19
20 #if defined(_MSC_VER)
21 # pragma warning(disable: 4345)
22 #endif
23
24 #include <boost/spirit/home/x3.hpp>
25 #include <boost/spirit/home/x3/support/ast/variant.hpp>
26 #include <boost/variant/recursive_variant.hpp>
27 #include <boost/variant/apply_visitor.hpp>
28 #include <boost/fusion/include/adapt_struct.hpp>
29
30 #include <list>
31 #include <numeric>
32
33 namespace x3 = boost::spirit::x3;
34
35 namespace client { namespace ast
36 {
37 ///////////////////////////////////////////////////////////////////////////
38 // The AST
39 ///////////////////////////////////////////////////////////////////////////
40 struct nil {};
41 struct signed_;
42 struct program;
43
44 typedef x3::variant<
45 nil
46 , unsigned int
47 , x3::forward_ast<signed_>
48 , x3::forward_ast<program>
49 >
50 operand;
51
52 struct signed_
53 {
54 char sign;
55 operand operand_;
56 };
57
58 struct operation
59 {
60 char operator_;
61 operand operand_;
62 };
63
64 struct program
65 {
66 operand first;
67 std::list<operation> rest;
68 };
69 }}
70
71 BOOST_FUSION_ADAPT_STRUCT(client::ast::signed_,
72 sign, operand_
73 )
74
75 BOOST_FUSION_ADAPT_STRUCT(client::ast::operation,
76 operator_, operand_
77 )
78
79 BOOST_FUSION_ADAPT_STRUCT(client::ast::program,
80 first, rest
81 )
82
83 namespace client { namespace ast
84 {
85 ///////////////////////////////////////////////////////////////////////////
86 // The AST Printer
87 ///////////////////////////////////////////////////////////////////////////
88 struct printer
89 {
90 typedef void result_type;
91
92 void operator()(nil) const {}
93 void operator()(unsigned int n) const { std::cout << n; }
94
95 void operator()(operation const& x) const
96 {
97 boost::apply_visitor(*this, x.operand_);
98 switch (x.operator_)
99 {
100 case '+': std::cout << " add"; break;
101 case '-': std::cout << " subt"; break;
102 case '*': std::cout << " mult"; break;
103 case '/': std::cout << " div"; break;
104 }
105 }
106
107 void operator()(signed_ const& x) const
108 {
109 boost::apply_visitor(*this, x.operand_);
110 switch (x.sign)
111 {
112 case '-': std::cout << " neg"; break;
113 case '+': std::cout << " pos"; break;
114 }
115 }
116
117 void operator()(program const& x) const
118 {
119 boost::apply_visitor(*this, x.first);
120 for (operation const& oper: x.rest)
121 {
122 std::cout << ' ';
123 (*this)(oper);
124 }
125 }
126 };
127
128 ///////////////////////////////////////////////////////////////////////////
129 // The AST evaluator
130 ///////////////////////////////////////////////////////////////////////////
131 struct eval
132 {
133 typedef int result_type;
134
135 int operator()(nil) const { BOOST_ASSERT(0); return 0; }
136 int operator()(unsigned int n) const { return n; }
137
138 int operator()(int lhs, operation const& x) const
139 {
140 int rhs = boost::apply_visitor(*this, x.operand_);
141 switch (x.operator_)
142 {
143 case '+': return lhs + rhs;
144 case '-': return lhs - rhs;
145 case '*': return lhs * rhs;
146 case '/': return lhs / rhs;
147 }
148 BOOST_ASSERT(0);
149 return 0;
150 }
151
152 int operator()(signed_ const& x) const
153 {
154 int rhs = boost::apply_visitor(*this, x.operand_);
155 switch (x.sign)
156 {
157 case '-': return -rhs;
158 case '+': return +rhs;
159 }
160 BOOST_ASSERT(0);
161 return 0;
162 }
163
164 int operator()(program const& x) const
165 {
166 return std::accumulate( x.rest.begin(), x.rest.end()
167 , boost::apply_visitor(*this, x.first)
168 , *this);
169 }
170 };
171 }}
172
173 namespace client
174 {
175 ///////////////////////////////////////////////////////////////////////////////
176 // The calculator grammar
177 ///////////////////////////////////////////////////////////////////////////////
178 namespace calculator_grammar
179 {
180 using parser_type =
181 x3::any_parser<
182 std::string::const_iterator
183 , ast::program
184 , decltype(x3::make_context<x3::skipper_tag>(x3::ascii::space))
185 >;
186
187 parser_type calculator();
188 }
189
190 auto const calculator = calculator_grammar::calculator();
191 }