Reputation: 239
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>’
Upvotes: 1
Views: 173
Reputation: 392833
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
boost::phoenix::function<>
or BOOST_PHOENIX_ADAPT_FUNCTION
etc)phx::bind
e.g. with a lambdaIn 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:
#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:
phrase_parse
:)Upvotes: 1
Reputation: 137301
Two separate issues:
phrase_parse
expects a Skipper as its fourth argument. Hence, you should use qi::phrase_parse(beg, end, par, ascii::space, result);
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.
Upvotes: 2