How to add qi :: characters in the <Iterator, double ()> grammar?

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) 
+2
source share
1 answer

Yes, I never added symbols directly from the semantic actions themselves (I prefer to build ASTs and then cross them).

The fact that you wrote it like that and the lack of SSCCE silenced me for a moment. It turns out that I just had to ignore the indirect "evidence" and went straight to the documents + win:

 var_decl = qi::as_string [ lexeme [ ( ( alpha >> *( alnum | '_' ) ) - vars ) ] ] [ phx::bind(vars.add, _1) ]; 

or

 var_decl = lexeme [ qi::raw [ ( alpha >> *( alnum | '_' ) ) - vars ] ] [ phx::bind(vars.add, _1) ]; 

and some similar spells will be applied

Change Here is the complete source compiled on MSVC 2010, with boost 1.47:

Output:

 T:\>cl /EHsc /I "c:\Program Files (x86)\boost\boost_1_47" test.cpp Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. test.cpp Microsoft (R) Incremental Linker Version 10.00.30319.01 Copyright (C) Microsoft Corporation. All rights reserved. /out:test.exe test.obj T:\>.\test.exe ********************************************************** * * * Command interface for VideoTraction4 * * * ********************************************************** Type an expression...or [q or Q] to quit 3*4+7 ------------------------- Parsing succeeded result = 19 ------------------------- 

On a slightly unrelated note: looks good - is it funny that the var_decl rule's public attribute looks like char ?

You might want to read the automatic rules and the %= operator; Without% =, the presence of semantic action will suppress all automatic distribution of attributes. This is useful if the required setting points do not exist. As indicated, the public attribute will never be assigned.

+2
source

Source: https://habr.com/ru/post/1441902/


All Articles