this article (boost spirit semantic action parameters) explains how invalidate match plain function signature
void f(int attribute, const boost::fusion::unused_type& it, bool& mflag) i invalidate match member function of grammar:
#include <boost/spirit/home/qi.hpp> #include <boost/spirit/home/phoenix.hpp> #include <iostream> #include <string> namespace qi = boost::spirit::qi; namespace phoenix = boost::phoenix; class moduleaccessmanager { public: bool getmodule(const std::string name) { if(name == "cat" || name == "dog") return true; else return false; } }; void globalismodule(std::string modulename, const boost::spirit::unused_type&, bool& mflag) { moduleaccessmanager acm; /* dirty workaround example */ if(acm.getmodule(modulename)) std::cout << "[ismodule] info: found module name >" << modulename << "<" << std::endl; else { std::cout << "[ismodule] error: no module name >" << modulename << "<" << std::endl; mflag = false; // no valid module name } } template <typename iterator, typename skipper> class modulecommandparser : public qi::grammar<iterator, skipper> { private: moduleaccessmanager* m_acm; qi::rule<iterator, skipper> start, module; public: std::string m_modulename; modulecommandparser(moduleaccessmanager* acm) : modulecommandparser::base_type(start) , m_acm(acm) , m_modulename("<empty>") { module = qi::as_string[qi::lexeme[+(~qi::char_(' '))]] [&globalismodule] // works fine // [phoenix::bind(&modulecommandparser::ismodule, this)] // compile error ; start = module >> qi::as_string[+(~qi::char_('\n'))]; }; void ismodule(std::string modulename, const boost::spirit::unused_type&, bool& mflag) { // check if module modulename exists if(m_acm->getmodule(modulename)) std::cout << "[ismodule] info: found module name >" << modulename << "<" << std::endl; else { std::cout << "[ismodule] error: no module name >" << modulename << "<" << std::endl; mflag = false; // no valid module name } }; }; int main() { moduleaccessmanager acm; modulecommandparser<std::string::const_iterator, qi::space_type> commandgrammar(&acm); std::string str; std::string::const_iterator first; std::string::const_iterator last; str = "cat run"; first = str.begin(); last = str.end(); qi::phrase_parse(first, last, commandgrammar, qi::space); str = "bird fly"; first = str.begin(); last = str.end(); qi::phrase_parse(first, last, commandgrammar, qi::space); } code on coliru: http://coliru.stacked-crooked.com/a/4319b38a6d36c362
the important part these 2 lines:
[&globalismodule] // works fine // [phoenix::bind(&modulecommandparser::ismodule, this)] // compile error using global function works fine, that's not option me because need access m_acm object specific parser.
how can bind member function semantic action , @ same time able invalidate match member function (using 3 argument function signature mentioned above)?
there 2 ways:
- you can assign
qi::_valusing phoenix actors - you can assign third parameter (
bool&) inside "raw" semantic action function
an example here:
the anatomy of semantic action function (with third argument):
in case have member function "raw semantic action function" signature. of course, you'll have bind this parameter (because it's non-static member function).
note in particular case, phoenix::bind not right bind use, phoenix actors considered "cooked" (not raw) semantic actions, , executed in spirit context.
you either
use
boost::bind(orstd::bind) bind function preserves arity (!) of member function:[boost::bind(&modulecommandparser::ismodule, this, ::_1, ::_2, ::_3)]this works: live on coliru
instead use "cooked" semantic action, directly assigning
_passcontext placeholder:[qi::_pass = phoenix::bind(&moduleaccessmanager::getmodule, m_acm, qi::_1)]this works too: live on coliru
the latter example, future reference:
#define boost_spirit_use_phoenix_v3 #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix.hpp> #include <iostream> #include <string> namespace qi = boost::spirit::qi; namespace phoenix = boost::phoenix; class moduleaccessmanager { public: bool getmodule(const std::string name) { return name == "cat" || name == "dog"; } }; void globalismodule(std::string modulename, const boost::spirit::unused_type&, bool& mflag) { moduleaccessmanager acm; /* dirty workaround example */ if(acm.getmodule(modulename)) std::cout << "[ismodule] info: found module name >" << modulename << "<" << std::endl; else { std::cout << "[ismodule] error: no module name >" << modulename << "<" << std::endl; mflag = false; // no valid module name } } template <typename iterator, typename skipper> class modulecommandparser : public qi::grammar<iterator, skipper> { private: moduleaccessmanager* m_acm; qi::rule<iterator, skipper> start, module; public: std::string m_modulename; modulecommandparser(moduleaccessmanager* acm) : modulecommandparser::base_type(start) , m_acm(acm) , m_modulename("<empty>") { using namespace phoenix::arg_names; module = qi::as_string[qi::lexeme[+(~qi::char_(' '))]] [qi::_pass = phoenix::bind(&moduleaccessmanager::getmodule, m_acm, qi::_1)] ; start = module >> qi::as_string[+(~qi::char_('\n'))]; }; }; int main() { moduleaccessmanager acm; modulecommandparser<std::string::const_iterator, qi::space_type> commandgrammar(&acm); std::string str; std::string::const_iterator first; std::string::const_iterator last; str = "cat run"; first = str.begin(); last = str.end(); std::cout << str << std::boolalpha << qi::phrase_parse(first, last, commandgrammar, qi::space) << "\n"; str = "bird fly"; first = str.begin(); last = str.end(); std::cout << str << std::boolalpha << qi::phrase_parse(first, last, commandgrammar, qi::space) << "\n"; }
Comments
Post a Comment