• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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