]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/classic/example/fundamental/more_calculators/vmachine_calc.cpp
1 /*=============================================================================
2 Copyright (c) 1998-2003 Joel de Guzman
3 http://spirit.sourceforge.net/
5 Use, modification and distribution is subject to the Boost Software
6 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9 ////////////////////////////////////////////////////////////////////////////
11 // The calculator using a simple virtual machine and compiler.
13 // Ported to v1.5 from the original v1.0 code by JDG
16 ////////////////////////////////////////////////////////////////////////////
17 #include <boost/spirit/include/classic_core.hpp>
22 ////////////////////////////////////////////////////////////////////////////
24 using namespace BOOST_SPIRIT_CLASSIC_NS
;
26 ///////////////////////////////////////////////////////////////////////////////
30 ///////////////////////////////////////////////////////////////////////////////
33 OP_NEG
, // negate the top stack entry
34 OP_ADD
, // add top two stack entries
35 OP_SUB
, // subtract top two stack entries
36 OP_MUL
, // multiply top two stack entries
37 OP_DIV
, // divide top two stack entries
38 OP_INT
, // push constant integer into the stack
39 OP_RET
// return from the interpreter
45 vmachine(unsigned stackSize
= 1024)
46 : stack(new int[stackSize
]),
48 ~vmachine() { delete [] stack
; }
49 int top() const { return stackPtr
[-1]; };
50 void execute(int code
[]);
59 vmachine::execute(int code
[])
70 stackPtr
[-1] = -stackPtr
[-1];
75 stackPtr
[-1] += stackPtr
[0];
80 stackPtr
[-1] -= stackPtr
[0];
85 stackPtr
[-1] *= stackPtr
[0];
90 stackPtr
[-1] /= stackPtr
[0];
94 // Check stack overflow here!
105 ///////////////////////////////////////////////////////////////////////////////
109 ///////////////////////////////////////////////////////////////////////////////
112 push_int(vector
<int>& code_
)
115 void operator()(char const* str
, char const* /*end*/) const
118 int n
= strtol(str
, 0, 10);
119 code
.push_back(OP_INT
);
121 cout
<< "push\t" << int(n
) << endl
;
129 push_op(int op_
, vector
<int>& code_
)
130 : op(op_
), code(code_
) {}
132 void operator()(char const*, char const*) const
164 template <typename GrammarT
>
166 compile(GrammarT
const& calc
, char const* expr
)
168 cout
<< "\n/////////////////////////////////////////////////////////\n\n";
170 parse_info
<char const*>
171 result
= parse(expr
, calc
, space_p
);
175 cout
<< "\t\t" << expr
<< " Parses OK\n\n\n";
176 calc
.code
.push_back(OP_RET
);
181 cout
<< "\t\t" << expr
<< " Fails parsing\n";
183 for (int i
= 0; i
< (result
.stop
- expr
); i
++)
185 cout
<< "^--Here\n\n\n";
190 ////////////////////////////////////////////////////////////////////////////
192 // Our calculator grammar
194 ////////////////////////////////////////////////////////////////////////////
195 struct calculator
: public grammar
<calculator
>
197 calculator(vector
<int>& code_
)
200 template <typename ScannerT
>
203 definition(calculator
const& self
)
206 lexeme_d
[ (+digit_p
)[push_int(self
.code
)] ]
211 | '(' >> expression
>> ')'
212 | ('-' >> factor
)[push_op(OP_NEG
, self
.code
)]
218 >> *( ('*' >> factor
)[push_op(OP_MUL
, self
.code
)]
219 | ('/' >> factor
)[push_op(OP_DIV
, self
.code
)]
225 >> *( ('+' >> term
)[push_op(OP_ADD
, self
.code
)]
226 | ('-' >> term
)[push_op(OP_SUB
, self
.code
)]
231 rule
<ScannerT
> expression
, term
, factor
, integer
;
233 rule
<ScannerT
> const&
234 start() const { return expression
; }
240 ////////////////////////////////////////////////////////////////////////////
244 ////////////////////////////////////////////////////////////////////////////
248 cout
<< "/////////////////////////////////////////////////////////\n\n";
249 cout
<< "\t\tA simple virtual machine...\n\n";
250 cout
<< "/////////////////////////////////////////////////////////\n\n";
251 cout
<< "Type an expression...or [q or Q] to quit\n\n";
253 vmachine mach
; // Our virtual machine
254 vector
<int> code
; // Our VM code
255 calculator
calc(code
); // Our parser
258 while (getline(cin
, str
))
260 if (str
.empty() || str
[0] == 'q' || str
[0] == 'Q')
264 if (compile(calc
, str
.c_str()))
266 mach
.execute(&*code
.begin());
267 cout
<< "\n\nresult = " << mach
.top() << "\n\n";
271 cout
<< "Bye... :-) \n\n";