|
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