]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
7c673cae FG |
21 | #include <boost/spirit/include/qi.hpp> |
22 | #include <boost/spirit/include/support_utree.hpp> | |
1e59de90 TL |
23 | #include <boost/phoenix/operator.hpp> |
24 | #include <boost/phoenix/function.hpp> | |
7c673cae FG |
25 | |
26 | #include <iostream> | |
27 | #include <string> | |
28 | ||
29 | #if BOOST_PHOENIX_VERSION == 0x2000 | |
30 | namespace boost { namespace phoenix | |
31 | { | |
32 | // There's a bug in the Phoenix V2 type deduction mechanism that prevents | |
33 | // correct return type deduction for the math operations below. Newer | |
34 | // versions of Phoenix will be switching to BOOST_TYPEOF. In the meantime, | |
35 | // we will use the specializations helping with return type deduction | |
36 | // below: | |
37 | template <> | |
38 | struct result_of_plus<spirit::utree&, spirit::utree&> | |
39 | { | |
40 | typedef spirit::utree type; | |
41 | }; | |
42 | ||
43 | template <> | |
44 | struct result_of_minus<spirit::utree&, spirit::utree&> | |
45 | { | |
46 | typedef spirit::utree type; | |
47 | }; | |
48 | ||
49 | template <> | |
50 | struct result_of_multiplies<spirit::utree&, spirit::utree&> | |
51 | { | |
52 | typedef spirit::utree type; | |
53 | }; | |
54 | ||
55 | template <> | |
56 | struct result_of_divides<spirit::utree&, spirit::utree&> | |
57 | { | |
58 | typedef spirit::utree type; | |
59 | }; | |
60 | ||
61 | template <> | |
62 | struct result_of_negate<spirit::utree&> | |
63 | { | |
64 | typedef spirit::utree type; | |
65 | }; | |
66 | }} | |
67 | #endif | |
68 | ||
69 | namespace client | |
70 | { | |
71 | namespace qi = boost::spirit::qi; | |
72 | namespace ascii = boost::spirit::ascii; | |
73 | namespace spirit = boost::spirit; | |
74 | ||
75 | /////////////////////////////////////////////////////////////////////////////// | |
76 | // Our calculator grammar | |
77 | /////////////////////////////////////////////////////////////////////////////// | |
78 | template <typename Iterator> | |
79 | struct calculator : qi::grammar<Iterator, ascii::space_type, spirit::utree()> | |
80 | { | |
81 | calculator() : calculator::base_type(expression) | |
82 | { | |
83 | using qi::uint_; | |
84 | using qi::_val; | |
85 | using qi::_1; | |
86 | ||
87 | expression = | |
88 | term [_val = _1] | |
89 | >> *( ('+' >> term [_val = _val + _1]) | |
90 | | ('-' >> term [_val = _val - _1]) | |
91 | ) | |
92 | ; | |
93 | ||
94 | term = | |
95 | factor [_val = _1] | |
96 | >> *( ('*' >> factor [_val = _val * _1]) | |
97 | | ('/' >> factor [_val = _val / _1]) | |
98 | ) | |
99 | ; | |
100 | ||
101 | factor = | |
102 | uint_ [_val = _1] | |
103 | | '(' >> expression [_val = _1] >> ')' | |
104 | | ('-' >> factor [_val = -_1]) | |
105 | | ('+' >> factor [_val = _1]) | |
106 | ; | |
107 | ||
108 | BOOST_SPIRIT_DEBUG_NODE(expression); | |
109 | BOOST_SPIRIT_DEBUG_NODE(term); | |
110 | BOOST_SPIRIT_DEBUG_NODE(factor); | |
111 | } | |
112 | ||
113 | qi::rule<Iterator, ascii::space_type, spirit::utree()> expression, term, factor; | |
114 | }; | |
115 | } | |
116 | ||
117 | /////////////////////////////////////////////////////////////////////////////// | |
118 | // Main program | |
119 | /////////////////////////////////////////////////////////////////////////////// | |
120 | int main() | |
121 | { | |
122 | std::cout << "/////////////////////////////////////////////////////////\n\n"; | |
123 | std::cout << "Expression parser...\n\n"; | |
124 | std::cout << "/////////////////////////////////////////////////////////\n\n"; | |
125 | std::cout << "Type an expression...or [q or Q] to quit\n\n"; | |
126 | ||
127 | using boost::spirit::ascii::space; | |
128 | using boost::spirit::utree; | |
129 | typedef std::string::const_iterator iterator_type; | |
130 | typedef client::calculator<iterator_type> calculator; | |
131 | ||
132 | calculator calc; // Our grammar | |
133 | ||
134 | std::string str; | |
135 | while (std::getline(std::cin, str)) | |
136 | { | |
137 | if (str.empty() || str[0] == 'q' || str[0] == 'Q') | |
138 | break; | |
139 | ||
140 | std::string::const_iterator iter = str.begin(); | |
141 | std::string::const_iterator end = str.end(); | |
142 | utree ut; | |
143 | bool r = phrase_parse(iter, end, calc, space, ut); | |
144 | ||
145 | if (r && iter == end) | |
146 | { | |
147 | std::cout << "-------------------------\n"; | |
148 | std::cout << "Parsing succeeded: " << ut << "\n"; | |
149 | std::cout << "-------------------------\n"; | |
150 | } | |
151 | else | |
152 | { | |
153 | std::string rest(iter, end); | |
154 | std::cout << "-------------------------\n"; | |
155 | std::cout << "Parsing failed\n"; | |
156 | std::cout << "stopped at: \": " << rest << "\"\n"; | |
157 | std::cout << "-------------------------\n"; | |
158 | } | |
159 | } | |
160 | ||
161 | std::cout << "Bye... :-) \n\n"; | |
162 | return 0; | |
163 | } | |
164 | ||
165 |