Phoenix :: bind for C ++ 11 lambdas in boost :: spirit :: qi semantic actions

My goal is to create a workaround so that I can use lambdas C ++ 11 within the semantic actions of Boost Spirit Qi, while having access to a more advanced set of qi placeholders, such as qi :: _ pass or qi :: _r1, without having to manually Retrieve them from the context object. I want to avoid writing Phoenix lambdas for some kind of nontrivial parsing logic, preferring the more direct syntax and semantics of C ++ available inside C ++ 11 lambdas.

The code below presents an idea that I use to work around. The idea is to use phoenix :: bind to bind to lambda and pass it the specific placeholders that I need. However, I get an extremely long templated compiler error (gcc 4.7.0, Boost 1.54), which I have no experience to interpret. I chose what I consider to be the most appropriate part, and placed it under the code.

I would like to know if it is possible that I am trying to do in this code with Boost Spirit, and if anyone can interpret the error message for me and tell me what is going wrong.

#include <string> #include <iostream> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix.hpp> namespace qi = boost::spirit::qi; namespace spirit = boost::spirit; namespace phoenix = boost::phoenix; int main() { std::string input{"test1 test2 test3 FOO!"}; typedef decltype(input.begin()) StringIter; qi::rule<StringIter, std::string()> parser = *( qi::char_ [ phoenix::bind( [] (char value) { std::cerr << value << std::endl; }, qi::_1 ) ] ); qi::parse(input.begin(), input.end(), parser); } 

(Note: I know that the specific task performed by this code will be easier with direct Phoenix constructs or can even be done thanks to Boost Spirit updates that only allow lambda with a single C ++ 11 argument, since it uses only the parsed value ( qi :: _ 1). However, this is a good minimal example of what I would like to do, and if I can get it to work, it should be easy to generalize.)

And, a bit of a compiler error (via STLfilt):

 test\testSpiritLearning.cpp:28:9: required from here D:\programming\lib\boost\boost_1_54_0/boost/spirit/home/support/action_dispatch.hpp:178:13: error: no match for call to '( const boost::phoenix::actor< boost::phoenix::composite< boost::phoenix::detail::function_eval<1> , boost::fusion::vector< boost::phoenix::value<main()::<lambda(char &)> > , boost::spirit::argument<0>, boost::fusion::void_ , boost::fusion::void_, boost::fusion::void_ , boost::fusion::void_, boost::fusion::void_ , boost::fusion::void_, boost::fusion::void_ , boost::fusion::void_ > > > ) ( boost::spirit::traits::pass_attribute< boost::spirit::qi::char_class< boost::spirit::tag::char_code< boost::spirit::tag::char_ , boost::spirit::char_encoding::standard > >, char, void >::type & , boost::spirit::context< boost::fusion::cons<basic_string<char> &, boost::fusion::nil> , boost::fusion::vector0<> > &, bool & )' 
+6
source share
1 answer

Just tell Boost that you want short-term edge compiler support: [1]

 #define BOOST_RESULT_OF_USE_DECLTYPE 

and you want to use Phoenix version V3:

 #define BOOST_SPIRIT_USE_PHOENIX_V3 

And he works

Watch Live on Coliru

Cause:

  • Using function objects in Phoenix actors suggests that your function object will have a special nested struct result template or just a simple typedef result_type . This is called the RESULT_OF protocol, see here:

    http://www.boost.org/doc/libs/1_55_0/libs/utility/utility.htm#result_of

    This protocol is required for C ++ 03 compatibility. However, lambdas does not have this . In fact, lambdas have unspecified types. This is one of the reasons why lambdas compilers always have decltype , so the RESULT_OF protocol is no longer required.

  • On the second #define you need to choose Phoenix V3, because Phoenix V2 just doesn't implement lambdas support. By default, Spirit V2 selects Phoenix V2 for history / compatibility reasons. In practice, Phoenix V3 is much more mature and fixes many (many) problems, so I recommend always working with BOOST_SPIRIT_USE_PHOENIX_V3


[1] may not be needed with very recent versions of some compilers

+4
source

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


All Articles