boost::spirit and boost in general for c++ people.

  • From: "Littlefield, Tyler" <tyler@xxxxxxxxxxxxx>
  • To: programmingblind@xxxxxxxxxxxxx
  • Date: Thu, 07 Apr 2011 07:09:15 -0600

hello all:
Recently I got into using boost a bit and started finding uses for it all over the place. I would like to encourage those who haven't yet and use c++ to check it out; it is quite powerful and can eas some of your work and provide really cool features along the way. For example: boost::function lets you take callbacks in multiple forms; boost::bind will let you bind a functor to it's arguments and pass that as your callback, which means you can bind to a static member function, a member function (and pass the object with boost::ref), a global function and you can also use boost::lambda. There are many more utilities out there; I highly recommend checking out boost::asio, boost::fusion, boost::function and boost::bind. In the spirit of convincing you all, I wrote a small calculator program that does single operations (1+3, 3*5), etc and returns the result. My next step is to split up my parsing into different rulesets and then work on generating an AST so that I can handle larger more complex calculations.
/*
A simple calculator, supports multiplication, division, addition and subtraction.
*/
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <iostream>
#include <string>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/container/vector/convert.hpp>
#include <boost/fusion/include/io.hpp>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phoenix = boost::phoenix;

struct calculation
{
  int a, b;
  char op;
};
BOOST_FUSION_ADAPT_STRUCT(calculation, (int, a) (char, op) (int, b) )

template <typename iterator>
class CParser:public qi::grammar<iterator, calculation(), qi::ascii::space_type>
{
  qi::rule <iterator, calculation(), qi::ascii::space_type> crule;
public:
  CParser():CParser::base_type(crule)
  {
    using qi::ascii::char_;
    using qi::int_;

    crule %= (int_ >>
              (char_('+')|char_('-')|char_('*')|char_('/')) >>
              int_);
  }
};

int main()
{
  CParser<std::string::iterator> p;
  std::string str;
  calculation result;

  std::cout << "Enter your calculation>";
getline(std::cin, str);

bool r = phrase_parse(str.begin(), str.end(), p, qi::ascii::space, result);
  if (r)
    {
std::cout << "a: " << result.a << " b: " << result.b << " op: " << result.op << std::endl;
      switch(result.op)
        {
        case '+':
          std::cout << "Result: " << (result.a + result.b) << std::endl;
          break;
        case '-':
          std::cout << "result: " << (result.a - result.b) << std::endl;
          break;
        case '*':
          std::cout << "Result: " << (result.a * result.b) << std::endl;
          break;
        case '/':
          if (result.a == 0)
            {
              std::cout << "Division by zero error." << std::endl;
              break;
            }
          std::cout << "result: " << (result.a / result.b) << std::endl;
          break;
        default:
          std::cout << "Invalid operation." << std::endl;
        }
    }
  else
    {
      std::cout << "Invalid input." << std::endl;
    }

  return 0;
}

--

Thanks,
Ty

__________
View the list's information and change your settings at //www.freelists.org/list/programmingblind

Other related posts: