Rise :: Spirit :: Qi

Consider the following code: (Boost.Spirit 2.5.1)

qi::parse(str.begin(), str.end(), (+qi::alpha)[[](const string& s){cout << s<< '\n';}] >> (*(qi::char_(',') | qi::char_('\''))) >> qi::uint_[[](int integer){cout << integer << '\n';}]); 

[[](int integer){cout << integer << '\n';}] works, but the same code for +qi::alpha does not work.

How can I fix the code?

+4
source share
2 answers

C ++ 0x / C ++ 11 lambdas not yet supported Boost Spirit 1 Change . Support seems to be improved (today I tested an older version with a higher version). Now with Boost 1_48 and g ++ 4.6.1 for just_work, the following appears. Hooray!

qi::as_string[]

I think you might want to learn about qi::as_string to get the public attribute as std::string instead of the standard std::vector<CharT> :

  qi::parse(str.begin(), str.end(), qi::as_string [ +qi::alpha ] [ [](const std::string&){std::cout << s << '\n';} ] >> (*(qi::char_(',') | qi::char_('\''))) >> qi::uint_ [ [](int integer){std::cout << integer << '\n';} ]); 

But, in my opinion, the syntax is not very friendly. Instead, I would prefer phoenixV2:

  qi::parse(str.begin(), str.end(), qi::as_string [ +qi::alpha ] [ std::cout << _1 << '\n' ] >> (*(qi::char_(',') | qi::char_('\''))) >> qi::uint_ [ std::cout << _1 << '\n' ]); 

This is already much shorter and less cryptic syntax. Take a look

A somewhat contrived example, demonstrating some of them in action, passes PLUS attributes directly to the parse function:

 #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix.hpp> #include <boost/spirit/include/phoenix_operator.hpp> #include <algorithm> namespace qi = boost::spirit::qi; namespace phx = boost::phoenix; bool reverse(std::string& value) { std::reverse(value.begin(), value.end()); return true; // false makes the parsing fail } int main() { std::string str("sometext,123"); auto f(str.begin()), l(str.end()); std::string s; unsigned int i; qi::parse(f,l, qi::as_string [ +qi::alpha ] [ reverse ] >> qi::omit [ *qi::char_(",\'") ] >> qi::uint_, s, i); std::cout << s << std::endl; std::cout << i << std::endl; } 

Outputs:

 txetemos 123 

1 PhoenixV3 may have some support for this at 1_48 (not verified); Do you want to

  #define BOOST_RESULT_OF_USE_DECLTYPE #define BOOST_SPIRIT_USE_PHOENIX_V3 

See http://boost.2283326.n4.nabble.com/Boost-Spirit-Phoenix-V3-An-Overview-td3583792.html

+6
source

Your code gives me the following compiler error skipping some bits

 /usr/include/boost/spirit/home/support/action_dispatch.hpp:142:13: error: no matching function for call to 'action_dispatch<>::do_call( const main()::<lambda(const string&)>&, action_dispatch<>::fwd_tag<std::vector<char>>, ... 

which boils down to the fact that the argument passed to your lambda is equal to vector<char> , not string

So, replace string with vector<char> :

 (+qi::alpha)[[](const std::vector<char>& s) { cout << std::string(s.begin(), s.end()) << '\n'; }] 
+5
source

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


All Articles