Hi,
I have tried various approaches to fixing this issue with maps and casts, splitting the parse into different sub-pieces, using std::vector directly and trying _r1 etc. but I seem to have failed to grasp something fundamental about the use of attributes.
I want to parse a line such as:
DEFMACRO macroname param1 param2 param3 ... paramN
and add macroname into a qi::symbols parser along with its list of params.
Matching on
lit("DEFMACRO") >> (+char_) >> predicate_
and putting into a defmacro struct works fine, but when I try to use the result or store it whole as the data element of a symbols parser I get errors of the form
cannot convert from 'const boost::phoenix::actor' to 'const client::defmacro'
- but whatever I try I always fail to "convert from 'const boost::phoenix::actor' to" whatever data type I am trying to use (eg straight to std::vector or other variations in structs. Also tried variations on syntax but so far drawn a blank.
Code fragment is below, followed by compiler output for this variation on my problem.
Any explanation of my failure to grasp some important concept very welcome.
Using VC++ 2008 with Spirit 1.42.
Thanks Rick
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_int.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <string>
#include <vector>
namespace client
{
namespace fusion = boost::fusion;
namespace phoenix = boost::phoenix;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
typedef std::vector<std::string> predicate;
struct defmacro
{
std::string name; // identifier for macro
predicate params; // parameters for macro
};
}
BOOST_FUSION_ADAPT_STRUCT(
client::defmacro,
(std::string, name)
(client::predicate, params)
)
namespace client
{
template <typename Iterator>
struct awe_grammar
: qi::grammar<Iterator, awe(), qi::locals<std::string>, ascii::space_type>
{
awe_grammar()
: awe_grammar::base_type(x, "x")
{
using qi::lit;
using qi::eol;
using qi::int_;
using ascii::char_;
using namespace qi::labels;
using phoenix::at_c;
long line_no=1;
qi::symbols<std::string, defmacro> macros;
eol_ = eol[ref(line_no)++];
predicate_ %= *(+char_);
defmacro_line_ %= (lit("DEFMACRO") >> (+char_) >> predicate_ >> eol_);
// ******** This line will not compile *************************
defmacro_ = defmacro_line_[macros.add(at_c<0>(_1),_1)];
// *************************************************************
}
qi::rule<Iterator, defmacro(), ascii::space_type> defmacro_line_;
qi::rule<Iterator, void(), ascii::space_type> defmacro_;
qi::rule<Iterator, predicate(), ascii::space_type> predicate_;
};
}
2>v:\awe\parser\parser\spirit\spirit_eg.cpp(XXX) : error C2664: 'const boost::spirit::qi::symbols<Char,T>::adder &boost::spirit::qi::symbols<Char,T>::adder::operator ()<boost::phoenix::actor<Eval>>(const Str &,const T &) const' : cannot convert parameter 2 from 'const boost::phoenix::actor<Eval>' to 'const client::defmacro &'
2> with
2> [
2> Char=std::string,
2> T=client::defmacro,
2> Eval=boost::phoenix::composite<boost::phoenix::at_eval<0>,boost::fusion::vector<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::fusion::void_>>,
2> Str=boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::at_eval<0>,boost::fusion::vector<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::fusion::void_>>>
2> ]
2> and
2> [
2> Eval=boost::spirit::argument<0>
2> ]
2> Reason: cannot convert from 'const boost::phoenix::actor<Eval>' to 'const client::defmacro'
2> with
2> [
2> Eval=boost::spirit::argument<0>
2> ]
2> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
2> v:\awe\parser\parser\spirit\spirit_eg.cpp(351) : while compiling class template member function 'client::awe_grammar<Iterator>::awe_grammar(void)'
2> with
2> [
2> Iterator=std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char>>
2> ]
2> v:\awe\parser\parser\spirit\spirit_eg.cpp(622) : see reference to class template instantiation 'client::awe_grammar<Iterator>' being compiled
2> with
2> [
2> Iterator=std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char>>
2> ]