Boost logo

Boost Users :

Subject: [Boost-users] a question on boost::spirit with a quick program.
From: Littlefield, Tyler (tyler_at_[hidden])
Date: 2011-04-06 18:12:05


Hello all:
Sorry for all the questions; I am kind of easing into boost and finding
cool things i can do with it, as well as uses for a couple of projects.
Eventually I would like to write a small scripting language using
boost::spirit, just to do it and get the practice using it. As a
starting point, I wrote a quick calculator (that just does small single
operations like x+x, x*x, etc). Now i have two questions. 1) My rule
seems to be off. the first number comes through clearly, but no matter
what I put in, I always get the first number and then a 42.
2) How would I go about extending this to implement order of operations,
parenthases, and longer operations (like 3+3*3)? I'm going to try to
implement a small function table so I can do tan(3), so I assume I will
need nultiple rules, how might that be accomplished?
Any comments and suggestions would be welcome. I have pasted the code
below. I was working from a tutorial, so early appologies if it feels
messy; I plan to clean up the namespace aliases and the using keywords.
/*
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;
using qi::double_;
using qi::_1;
using ascii::space;
using phoenix::ref;
using std::cout;
using std::endl;

typedef struct
{
   int a, b;
   char op;
} calculation;

BOOST_FUSION_ADAPT_STRUCT(calculation, (int, a) (int, b) (char, op) )

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

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

int main()
{
   using std::cout;
   using std::cin;
   using std::endl;
   using boost::fusion::vector;

   CParser<std::string::iterator> p;
   std::string str;
   calculation result;

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

   return 0;
}

-- 
Thanks,
Ty

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net