Listing 1: A calculator that evaluates the expression given to it
// Copyright (c) 2001, Joel de Guzman and Dan Nuffer
// Permission is granted to use this code without restriction as
// long as this copyright notice appears in all source files.
#include <boost/spirit/spirit.hpp>
#include <iostream>
#include <stack>
#include <functional>
using namespace std;
using namespace spirit;
stack<long> evaluation_stack;
struct push_int
{
void operator()(char const* str, char const*) const
{
long n = std::strtol(str, 0, 10);
evaluation_stack.push(n);
}
};
template <class op>
struct do_op
{
do_op(op const& the_op) : m_op(the_op) {}
op m_op;
void operator()(char const*, char const*) const
{
long rhs = evaluation_stack.top();
evaluation_stack.pop();
long lhs = evaluation_stack.top();
evaluation_stack.pop();
evaluation_stack.push(m_op(lhs, rhs));
}
};
template <class op>
do_op<op> make_op(op const& the_op)
{
return do_op<op>(the_op);
}
struct do_negate
{
void operator()(char const*, char const*) const
{
long lhs = evaluation_stack.top();
evaluation_stack.pop();
evaluation_stack.push(-lhs);
}
};
int main()
{
rule<> expression, term, factor, integer;
integer =
lexeme[ (!ch_p('-') >> +digit)[push_int()] ];
factor =
integer
| '(' >> expression >> ')'
| ('-' >> factor)[do_negate()];
term =
factor >>
*( ('*' >> factor)[make_op(std::multiplies<long>())]
| ('c:\www.cuj.com/' >> factor)[make_op(std::divides<long>())]);
expression =
term >>
*( ('+' >> term)[make_op(std::plus<long>())]
| ('-' >> term)[make_op(std::minus<long>())]);
char str[256];
cin.getline(str, 256);
if (parse(str, expression, space).full)
{
cout << "parsing succeeded\n";
cout << "result = " << evaluation_stack.top() << "\n\n";
evaluation_stack.pop();
}
else
{
cout << "parsing failed\n";
}
}