1 /*=============================================================================
2 Copyright (c) 2001-2003 Dan Nuffer
3 Copyright (c) 2002-2003 Joel de Guzman
4 http://spirit.sourceforge.net/
5
6 Use, modification and distribution is subject to the Boost Software
7 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8 http://www.boost.org/LICENSE_1_0.txt)
9 =============================================================================*/
10 ////////////////////////////////////////////////////////////////////////////
11 //
12 // Full calculator example using STL functors
13 // This is discussed in the "Functional" chapter in the Spirit User's Guide.
14 //
15 // Ported to Spirit v1.5 from v1.2/1.3 example by Dan Nuffer
16 // [ JDG 9/18/2002 ]
17 //
18 ////////////////////////////////////////////////////////////////////////////
19 #include <boost/spirit/include/classic_core.hpp>
20 #include <iostream>
21 #include <stack>
22 #include <functional>
23 #include <string>
24
25 ////////////////////////////////////////////////////////////////////////////
26 using namespace std;
27 using namespace BOOST_SPIRIT_CLASSIC_NS;
28
29 ////////////////////////////////////////////////////////////////////////////
30 //
31 // Semantic actions
32 //
33 ////////////////////////////////////////////////////////////////////////////
34 struct push_int
35 {
push_intpush_int36 push_int(stack<long>& eval_)
37 : eval(eval_) {}
38
operator ()push_int39 void operator()(char const* str, char const* /*end*/) const
40 {
41 long n = strtol(str, 0, 10);
42 eval.push(n);
43 cout << "push\t" << long(n) << endl;
44 }
45
46 stack<long>& eval;
47 };
48
49 template <typename op>
50 struct do_op
51 {
do_opdo_op52 do_op(op const& the_op, stack<long>& eval_)
53 : m_op(the_op), eval(eval_) {}
54
operator ()do_op55 void operator()(char const*, char const*) const
56 {
57 long rhs = eval.top();
58 eval.pop();
59 long lhs = eval.top();
60 eval.pop();
61
62 cout << "popped " << lhs << " and " << rhs << " from the stack. ";
63 cout << "pushing " << m_op(lhs, rhs) << " onto the stack.\n";
64 eval.push(m_op(lhs, rhs));
65 }
66
67 op m_op;
68 stack<long>& eval;
69 };
70
71 template <class op>
72 do_op<op>
make_op(op const & the_op,stack<long> & eval)73 make_op(op const& the_op, stack<long>& eval)
74 {
75 return do_op<op>(the_op, eval);
76 }
77
78 struct do_negate
79 {
do_negatedo_negate80 do_negate(stack<long>& eval_)
81 : eval(eval_) {}
82
operator ()do_negate83 void operator()(char const*, char const*) const
84 {
85 long lhs = eval.top();
86 eval.pop();
87
88 cout << "popped " << lhs << " from the stack. ";
89 cout << "pushing " << -lhs << " onto the stack.\n";
90 eval.push(-lhs);
91 }
92
93 stack<long>& eval;
94 };
95
96 ////////////////////////////////////////////////////////////////////////////
97 //
98 // Our calculator grammar
99 //
100 ////////////////////////////////////////////////////////////////////////////
101 struct calculator : public grammar<calculator>
102 {
calculatorcalculator103 calculator(stack<long>& eval_)
104 : eval(eval_) {}
105
106 template <typename ScannerT>
107 struct definition
108 {
definitioncalculator::definition109 definition(calculator const& self)
110 {
111 integer =
112 lexeme_d[ (+digit_p)[push_int(self.eval)] ]
113 ;
114
115 factor =
116 integer
117 | '(' >> expression >> ')'
118 | ('-' >> factor)[do_negate(self.eval)]
119 | ('+' >> factor)
120 ;
121
122 term =
123 factor
124 >> *( ('*' >> factor)[make_op(multiplies<long>(), self.eval)]
125 | ('/' >> factor)[make_op(divides<long>(), self.eval)]
126 )
127 ;
128
129 expression =
130 term
131 >> *( ('+' >> term)[make_op(plus<long>(), self.eval)]
132 | ('-' >> term)[make_op(minus<long>(), self.eval)]
133 )
134 ;
135 }
136
137 rule<ScannerT> expression, term, factor, integer;
138 rule<ScannerT> const&
startcalculator::definition139 start() const { return expression; }
140 };
141
142 stack<long>& eval;
143 };
144
145 ////////////////////////////////////////////////////////////////////////////
146 //
147 // Main program
148 //
149 ////////////////////////////////////////////////////////////////////////////
150 int
main()151 main()
152 {
153 cout << "/////////////////////////////////////////////////////////\n\n";
154 cout << "\t\tThe simplest working calculator...\n\n";
155 cout << "/////////////////////////////////////////////////////////\n\n";
156 cout << "Type an expression...or [q or Q] to quit\n\n";
157
158 stack<long> eval;
159 calculator calc(eval); // Our parser
160
161 string str;
162 while (getline(cin, str))
163 {
164 if (str.empty() || str[0] == 'q' || str[0] == 'Q')
165 break;
166
167 parse_info<> info = parse(str.c_str(), calc, space_p);
168
169 if (info.full)
170 {
171 cout << "-------------------------\n";
172 cout << "Parsing succeeded\n";
173 cout << "-------------------------\n";
174 }
175 else
176 {
177 cout << "-------------------------\n";
178 cout << "Parsing failed\n";
179 cout << "stopped at: \": " << info.stop << "\"\n";
180 cout << "-------------------------\n";
181 }
182 }
183
184 cout << "Bye... :-) \n\n";
185 return 0;
186 }
187
188
189