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";
    }
}