I am trying to use the Boost.Spirit library (V. 2.5) to create a mini calculator. Opportunities that I want to implement: - the basic calculus (+, -, /, *), which works - some functions (for example, min, max) that also work - the declaration / assignment of double variables, and there is a problem ... when I add "[vars.add]" I get a compilation error (the template parameter is ambiguous). I tried "add (char _ (_ 1)", "add (_1)", ... and nothing works. I obviously missed something (without really understanding anything). If someone could help me with this, I would be very grateful!
Here is the source:
#include <boost/config/warning_disable.hpp> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix_operator.hpp> #include <boost/spirit/home/phoenix/statement/if.hpp> #include <boost/spirit/home/phoenix/bind/bind_function.hpp> #include <iostream> #include <string> namespace client { namespace qi = boost::spirit::qi; namespace ascii = boost::spirit::ascii; namespace phx = boost::phoenix; struct vars_ : qi::symbols<char, double> { vars_() { add("ans" , 0); } } vars; template <typename Iterator> struct parser : qi::grammar<Iterator, double()> { parser() : parser::base_type(function) { using qi::eps; using qi::lit; using qi::_val; using qi::_1; using ascii::char_; using qi::double_; using qi::string; using qi::lexeme; using boost::phoenix::if_; using qi::alpha; using qi::alnum; MAX = lexeme[string("max") | string("MAX")]; //define max symbol MIN = lexeme[string("min") | string("MIN")]; //define min symbol D = lexeme[string("d") | string("D")]; //define distance symbol ANS = lexeme[string("ans") | string("ANS")]; //not working yet function = expression [_val = _1] | declaration | assignment | ( MAX >> "(" >> function [_val = _1] >> +(',' >> function [if_(_1 > _val)[_val = _1]]) >> ')') // call : max(function,...) | ( MIN >> "(" >> function [_val = _1] >> +(',' >> function [if_(_1 < _val)[_val = _1]]) >> ')') // call : min(function,...) | ( D >> "(" >> (function >> ',' >> function) >> ')'); // call : d(point1,point2) not implemented yet expression = term [_val = _1] >> *( ('+' >> term [_val += _1]) | ('-' >> term [_val -= _1])); term = factor [_val = _1] >> *( ('*' >> factor [_val *= _1]) | ('/' >> factor [_val /= _1])); factor = double_ [_val = _1] | (vars [_val += _1] ) | '(' >> expression [_val = _1] >> ')' | ('-' >> factor [_val = -_1]) | ('+' >> factor [_val = _1]) | declaration; ; assignment = vars >> '=' >> function; var_decl = lexeme [ qi::raw [ ( alpha >> *( alnum | '_' ) ) - vars ] ] //[ phx::bind(vars.add, _1) ] ; declaration = "var " >> var_decl >> *( ',' >> var_decl ); } qi::rule<Iterator, double()> MAX, MIN, D, ANS, expression, term, factor, function, assignment, var_decl, declaration; }; } /////////////////////////////////////////////////////////////////////////////// // Main program /////////////////////////////////////////////////////////////////////////////// int main() { std::cout << "**********************************************************" << std::endl; std::cout << "* *" << std::endl; std::cout << "* Command interface for VideoTraction4 *" << std::endl; std::cout << "* *" << std::endl; std::cout << "**********************************************************" << std::endl << std::endl; std::cout << "Type an expression...or [q or Q] to quit" << std::endl << std::endl; typedef std::string::const_iterator iterator_type; typedef client::parser<iterator_type> parser; parser _parser; // Our grammar std::string str; double result; while (std::getline(std::cin, str)) { if (str.empty() || str[0] == 'q' || str[0] == 'Q') break; std::string::const_iterator iter = str.begin(); std::string::const_iterator end = str.end(); bool r = parse(iter, end, _parser, result); if (r && iter == end) { std::cout << "-------------------------\n"; std::cout << "Parsing succeeded\n"; std::cout << "result = " << result << std::endl; std::cout << "-------------------------\n"; client::vars.remove("ans"); client::vars.add("ans",result); } else { std::string rest(iter, end); std::cout << "-------------------------\n"; std::cout << "Parsing failed\n"; std::cout << "stopped at: \": " << rest << "\"\n"; std::cout << "-------------------------\n"; } } std::cout << "Bye... :-) \n\n"; return 0; }
I would like to do things like:
var i,j i = 1 j = max(2*(i+1),5)