1

following is a minimal size program which I am not able to compile in Boost::spirit library.

 #include <iostream> #include <string> #include <boost/spirit/include/qi.hpp> #include <boost/lexical_cast.hpp> using namespace boost::spirit; template <typename Iterator> struct z3_exp_grammars : qi::grammar<Iterator, std::string(), ascii::space_type> { z3_exp_grammars() : z3_exp_grammars::base_type(text) { text = qi::int_[qi::_val = boost::lexical_cast<std::string>(qi::_1)]; } qi::rule<Iterator, std::string(), ascii::space_type> text; }; int main(){ std::string test("3"); std::string result; std::string::const_iterator beg = test.begin(); std::string::const_iterator end = test.end(); typedef z3_exp_grammars<std::string::const_iterator> z3_exp_grammars; z3_exp_grammars par; qi::phrase_parse(beg,end,par,result); std::cout<<"Result is "<<result<<std::endl; } 

I am expecting to see the string 3 in variable result but the code is not compiling. Rather than looking at error log (which is very threatening because of templates) it will be great if someone can spot my error in the code. Thanks for your help.

Updating the question with the compilation errors that I get after compiling the same code as given by T.C.

Test.cpp:9:11: error: expected nested-name-specifier before ‘result_type’ Test.cpp:9:11: error: using-declaration for non-member at class scope Test.cpp:9:23: error: expected ‘;’ before ‘=’ token Test.cpp:9:23: error: expected unqualified-id before ‘=’ token In file included from /home/jaganmohini/Downloads/boost_1_58_0/boost/proto/proto_fwd.hpp:28:0, from /home/jaganmohini/Downloads/boost_1_58_0/boost/phoenix/core/limits.hpp:26, from /home/jaganmohini/Downloads/boost_1_58_0/boost/spirit/include/phoenix_limits.hpp:11, from /home/jaganmohini/Downloads/boost_1_58_0/boost/spirit/home/support/meta_compiler.hpp:16, from /home/jaganmohini/Downloads/boost_1_58_0/boost/spirit/home/qi/meta_compiler.hpp:14, from /home/jaganmohini/Downloads/boost_1_58_0/boost/spirit/home/qi/action/action.hpp:14, from /home/jaganmohini/Downloads/boost_1_58_0/boost/spirit/home/qi/action.hpp:14, from /home/jaganmohini/Downloads/boost_1_58_0/boost/spirit/home/qi.hpp:14, from /home/jaganmohini/Downloads/boost_1_58_0/boost/spirit/include/qi.hpp:16, from Test.cpp:3: /home/jaganmohini/Downloads/boost_1_58_0/boost/utility/result_of.hpp: In instantiation of ‘boost::detail::result_of_nested_result<const to_string_, const to_string_(int&)>’: /home/jaganmohini/Downloads/boost_1_58_0/boost/utility/result_of.hpp:197:1: instantiated from ‘boost::detail::tr1_result_of_impl<const to_string_, const to_string_(int&), false>’ 
1
  • Those template error messages might be threatening for you, but they also might help other people to find the error. Can you please attach the compiler message? Commented Jun 12, 2015 at 8:37

2 Answers 2

2

Two separate issues:

  1. phrase_parse expects a Skipper as its fourth argument. Hence, you should use qi::phrase_parse(beg, end, par, ascii::space, result);

  2. You can't use boost::lexical_cast on a phoenix placeholder like that. It's eagerly evaluated. You need to create a lazy function:

    struct to_string_ { using result_type = std::string; template<class T> std::string operator()(const T& arg) const { return boost::lexical_cast<std::string>(arg); } }; boost::phoenix::function<to_string_> to_string; 

    and do

    text = qi::int_[qi::_val = to_string(qi::_1)]; 

Demo.

Sign up to request clarification or add additional context in comments.

4 Comments

Gah. You beat me :) I had my answer drafted for a while because busy :S
I am surprised, because your demo program is compiling and running fine but the same program in my machine is giving the following compilation errors; I have updated the question with new compilation errors.
@chinu Looks like compiler doesn't have C++11 support. (Or doesn't have it enabled - which version of GCC is this?) For C++03, use typedef std::string result_type; instead of using result_type = std::string;.
Great.. Thanks it worked. I have g++ 4.5.2 and I think it does not have c++11 support. Thanks again.
1

You cannot perform "eager" functions on "lazy" actors like qi::_1.

The type of qi::_1 is simply qi::_1_type: it's a placeholder.

Either you have to

  • adapt the function
  • create/wrap a lazy functor (boost::phoenix::function<> or BOOST_PHOENIX_ADAPT_FUNCTION etc)
  • use phx::bind e.g. with a lambda
  • pass a raw semantic action calleable (see docs)

In this case I would do neither of the above, because it's fishy to use lexical_cast when implementing a parser (that's like putting the receipt of you bank account in a sock under the bed. Or like driving to the bike-shed by car).

I'd parse to an int, here (because that's exactly what qi::int_ is designed to match and expose).

If you want the input string that was matched as an int, use

 text = qi::raw [ qi::int_ ]; 

If you insist on "reformatting", I'd do:

Live On Coliru

#include <iostream> #include <string> #include <boost/spirit/include/qi.hpp> #include <boost/lexical_cast.hpp> namespace qi = boost::spirit::qi; int main() { using It = std::string::const_iterator; std::string const test("3"); It beg = test.begin(), end = test.end(); int result; if (qi::phrase_parse(beg, end, qi::int_, qi::space, result)) std::cout << "Result is " << boost::lexical_cast<std::string>(result) << std::endl; } 

Notes:

  • separate concerns (parsing vs. presentation)
  • pass the skipper in phrase_parse :)

1 Comment

Thanks for the informative answer. But as I said this was a minimal example of non-compiling code. I am trying to write a parser which, given a string, constructs an expression in Z3 (a SMT solver) syntax. For that I was experimenting with spirit and especially with this example to understand its working. So I need the grammar structure and the rules inside them. I am sorry if I made the minimal example so simplistic but in a nutshell I am trying to use the grammar structure and synthesized attributes of the rules for my situation.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.