]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/example/qi/calc_utree_ast.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / spirit / example / qi / calc_utree_ast.cpp
1 /*=============================================================================
2 Copyright (c) 2001-2011 Hartmut Kaiser
3 Copyright (c) 2001-2011 Joel de Guzman
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 // Plain calculator example demonstrating the grammar. The parser is a
11 // syntax checker only and does not do any semantic evaluation.
12 //
13 // [ JDG May 10, 2002 ] spirit1
14 // [ JDG March 4, 2007 ] spirit2
15 // [ HK November 30, 2010 ] spirit2/utree
16 //
17 ///////////////////////////////////////////////////////////////////////////////
18
19 // #define BOOST_SPIRIT_DEBUG
20
21 #include <boost/config/warning_disable.hpp>
22 #include <boost/spirit/include/support_utree.hpp>
23 #include <boost/spirit/include/qi.hpp>
24 #include <boost/spirit/include/phoenix_operator.hpp>
25 #include <boost/spirit/include/phoenix_function.hpp>
26
27 #include <iostream>
28 #include <string>
29
30 namespace client
31 {
32 namespace qi = boost::spirit::qi;
33 namespace ascii = boost::spirit::ascii;
34 namespace spirit = boost::spirit;
35
36 struct expr
37 {
38 template <typename T1, typename T2 = void>
39 struct result { typedef void type; };
40
41 expr(char op) : op(op) {}
42
43 void operator()(spirit::utree& expr, spirit::utree const& rhs) const
44 {
45 spirit::utree lhs;
46 lhs.swap(expr);
47 expr.push_back(spirit::utf8_symbol_range_type(&op, &op+1));
48 expr.push_back(lhs);
49 expr.push_back(rhs);
50 }
51
52 char const op;
53 };
54 boost::phoenix::function<expr> const plus = expr('+');
55 boost::phoenix::function<expr> const minus = expr('-');
56 boost::phoenix::function<expr> const times = expr('*');
57 boost::phoenix::function<expr> const divide = expr('/');
58
59 struct negate_expr
60 {
61 template <typename T1, typename T2 = void>
62 struct result { typedef void type; };
63
64 void operator()(spirit::utree& expr, spirit::utree const& rhs) const
65 {
66 char const op = '-';
67 expr.clear();
68 expr.push_back(spirit::utf8_symbol_range_type(&op, &op+1));
69 expr.push_back(rhs);
70 }
71 };
72 boost::phoenix::function<negate_expr> neg;
73
74 ///////////////////////////////////////////////////////////////////////////////
75 // Our calculator grammar
76 ///////////////////////////////////////////////////////////////////////////////
77 template <typename Iterator>
78 struct calculator : qi::grammar<Iterator, ascii::space_type, spirit::utree()>
79 {
80 calculator() : calculator::base_type(expression)
81 {
82 using qi::uint_;
83 using qi::_val;
84 using qi::_1;
85
86 expression =
87 term [_val = _1]
88 >> *( ('+' >> term [plus(_val, _1)])
89 | ('-' >> term [minus(_val, _1)])
90 )
91 ;
92
93 term =
94 factor [_val = _1]
95 >> *( ('*' >> factor [times(_val, _1)])
96 | ('/' >> factor [divide(_val, _1)])
97 )
98 ;
99
100 factor =
101 uint_ [_val = _1]
102 | '(' >> expression [_val = _1] >> ')'
103 | ('-' >> factor [neg(_val, _1)])
104 | ('+' >> factor [_val = _1])
105 ;
106
107 BOOST_SPIRIT_DEBUG_NODE(expression);
108 BOOST_SPIRIT_DEBUG_NODE(term);
109 BOOST_SPIRIT_DEBUG_NODE(factor);
110 }
111
112 qi::rule<Iterator, ascii::space_type, spirit::utree()> expression, term, factor;
113 };
114 }
115
116 ///////////////////////////////////////////////////////////////////////////////
117 // Main program
118 ///////////////////////////////////////////////////////////////////////////////
119 int main()
120 {
121 std::cout << "/////////////////////////////////////////////////////////\n\n";
122 std::cout << "Expression parser...\n\n";
123 std::cout << "/////////////////////////////////////////////////////////\n\n";
124 std::cout << "Type an expression...or [q or Q] to quit\n\n";
125
126 using boost::spirit::ascii::space;
127 using boost::spirit::utree;
128 typedef std::string::const_iterator iterator_type;
129 typedef client::calculator<iterator_type> calculator;
130
131 calculator calc; // Our grammar
132
133 std::string str;
134 while (std::getline(std::cin, str))
135 {
136 if (str.empty() || str[0] == 'q' || str[0] == 'Q')
137 break;
138
139 std::string::const_iterator iter = str.begin();
140 std::string::const_iterator end = str.end();
141 utree ut;
142 bool r = phrase_parse(iter, end, calc, space, ut);
143
144 if (r && iter == end)
145 {
146 std::cout << "-------------------------\n";
147 std::cout << "Parsing succeeded: " << ut << "\n";
148 std::cout << "-------------------------\n";
149 }
150 else
151 {
152 std::string rest(iter, end);
153 std::cout << "-------------------------\n";
154 std::cout << "Parsing failed\n";
155 std::cout << "stopped at: \": " << rest << "\"\n";
156 std::cout << "-------------------------\n";
157 }
158 }
159
160 std::cout << "Bye... :-) \n\n";
161 return 0;
162 }
163
164