• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2001-2003 Dan Nuffer
3     Copyright (c) 2001-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 with variables
13 //  [ JDG 9/18/2002 ]
14 //
15 ///////////////////////////////////////////////////////////////////////////////
16 #include <boost/spirit/include/classic_core.hpp>
17 #include <boost/spirit/include/classic_symbols.hpp>
18 #include <iostream>
19 #include <stack>
20 #include <functional>
21 #include <string>
22 
23 using namespace std;
24 using namespace BOOST_SPIRIT_CLASSIC_NS;
25 
26 ///////////////////////////////////////////////////////////////////////////////
27 //
28 //  Semantic actions
29 //
30 ///////////////////////////////////////////////////////////////////////////////
31 struct push_num
32 {
push_numpush_num33     push_num(stack<double>& eval_)
34     : eval(eval_) {}
35 
operator ()push_num36     void operator()(double n) const
37     {
38         eval.push(n);
39         cout << "push\t" << n << endl;
40     }
41 
42     stack<double>& eval;
43 };
44 
45 template <typename op>
46 struct do_op
47 {
do_opdo_op48     do_op(op const& the_op, stack<double>& eval_)
49     : m_op(the_op), eval(eval_) {}
50 
operator ()do_op51     void operator()(char const*, char const*) const
52     {
53         double rhs = eval.top();
54         eval.pop();
55         double lhs = eval.top();
56         eval.pop();
57 
58         cout << "popped " << lhs << " and " << rhs << " from the stack. ";
59         cout << "pushing " << m_op(lhs, rhs) << " onto the stack.\n";
60         eval.push(m_op(lhs, rhs));
61     }
62 
63     op m_op;
64     stack<double>& eval;
65 };
66 
67 template <class op>
68 do_op<op>
make_op(op const & the_op,stack<double> & eval)69 make_op(op const& the_op, stack<double>& eval)
70 {
71     return do_op<op>(the_op, eval);
72 }
73 
74 struct do_negate
75 {
do_negatedo_negate76     do_negate(stack<double>& eval_)
77     : eval(eval_) {}
78 
operator ()do_negate79     void operator()(char const*, char const*) const
80     {
81         double lhs = eval.top();
82         eval.pop();
83 
84         cout << "popped " << lhs << " from the stack. ";
85         cout << "pushing " << -lhs << " onto the stack.\n";
86         eval.push(-lhs);
87     }
88 
89     stack<double>& eval;
90 };
91 
92 struct get_var
93 {
get_varget_var94     get_var(stack<double>& eval_)
95     : eval(eval_) {}
96 
operator ()get_var97     void operator()(double n) const
98     {
99         eval.push(n);
100         cout << "push\t" << n << endl;
101     }
102 
103     stack<double>& eval;
104 };
105 
106 struct set_var
107 {
set_varset_var108     set_var(double*& var_)
109     : var(var_) {}
110 
operator ()set_var111     void operator()(double& n) const
112     {
113         var = &n;
114     }
115 
116     double*& var;
117 };
118 
119 struct redecl_var
120 {
operator ()redecl_var121     void operator()(double& /*n*/) const
122     {
123         cout << "Warning. You are attempting to re-declare a var.\n";
124     }
125 };
126 
127 struct do_assign
128 {
do_assigndo_assign129     do_assign(double*& var_, stack<double>& eval_)
130     : var(var_), eval(eval_) {}
131 
operator ()do_assign132     void operator()(char const*, char const*) const
133     {
134         if (var != 0)
135         {
136             *var = eval.top();
137             cout << "assigning\n";
138         }
139     }
140 
141     double*& var;
142     stack<double>&  eval;
143 };
144 
145 ///////////////////////////////////////////////////////////////////////////////
146 //
147 //  Our calculator grammar
148 //
149 ///////////////////////////////////////////////////////////////////////////////
150 struct calculator : public grammar<calculator>
151 {
calculatorcalculator152     calculator(stack<double>& eval_)
153     : eval(eval_) {}
154 
155     template <typename ScannerT>
156     struct definition
157     {
definitioncalculator::definition158         definition(calculator const& self)
159         {
160             factor =
161                     real_p[push_num(self.eval)]
162                 |   vars[get_var(self.eval)]
163                 |   '(' >> expression >> ')'
164                 |   ('-' >> factor)[do_negate(self.eval)]
165                 ;
166 
167             term =
168                 factor
169                 >> *(   ('*' >> factor)[make_op(multiplies<double>(), self.eval)]
170                     |   ('/' >> factor)[make_op(divides<double>(), self.eval)]
171                     )
172                     ;
173 
174             expression =
175                 term
176                 >> *(  ('+' >> term)[make_op(plus<double>(), self.eval)]
177                     |   ('-' >> term)[make_op(minus<double>(), self.eval)]
178                     )
179                     ;
180 
181             assignment =
182                 vars[set_var(self.var)]
183                 >> '=' >> expression[do_assign(self.var, self.eval)]
184                 ;
185 
186             var_decl =
187                 lexeme_d
188                 [
189                     ((alpha_p >> *(alnum_p | '_'))
190                         - vars[redecl_var()])[vars.add]
191                 ]
192                 ;
193 
194             declaration =
195                 lexeme_d["var" >> space_p] >> var_decl >> *(',' >> var_decl)
196                 ;
197 
198             statement =
199                 declaration | assignment | '?' >> expression
200                 ;
201         }
202 
203         symbols<double>     vars;
204         rule<ScannerT>      statement, declaration, var_decl,
205                             assignment, expression, term, factor;
206 
207         rule<ScannerT> const&
startcalculator::definition208         start() const { return statement; }
209     };
210 
211     mutable double* var;
212     stack<double>&  eval;
213 };
214 
215 ///////////////////////////////////////////////////////////////////////////////
216 //
217 //  Main program
218 //
219 ///////////////////////////////////////////////////////////////////////////////
220 int
main()221 main()
222 {
223     cout << "/////////////////////////////////////////////////////////\n\n";
224     cout << "\t\tThe calculator with variables...\n\n";
225     cout << "/////////////////////////////////////////////////////////\n\n";
226     cout << "Type a statement...or [q or Q] to quit\n\n";
227     cout << "Variables may be declared:\t\tExample: var i, j, k\n";
228     cout << "Assigning to a variable:\t\tExample: i = 10 * j\n";
229     cout << "To evaluate an expression:\t\tExample: ? i * 3.33E-3\n\n";
230 
231     stack<double>   eval;
232     calculator      calc(eval); //  Our parser
233 
234     string str;
235     while (getline(cin, str))
236     {
237         if (str.empty() || str[0] == 'q' || str[0] == 'Q')
238             break;
239 
240         parse_info<> info = parse(str.c_str(), calc, space_p);
241 
242         if (info.full)
243         {
244             cout << "-------------------------\n";
245             cout << "Parsing succeeded\n";
246             cout << "-------------------------\n";
247         }
248         else
249         {
250             cout << "-------------------------\n";
251             cout << "Parsing failed\n";
252             cout << "stopped at: \": " << info.stop << "\"\n";
253             cout << "-------------------------\n";
254         }
255     }
256 
257     cout << "Bye... :-) \n\n";
258     return 0;
259 }
260 
261 
262