Getting result from boost spirit grammar (phoenix push_back causes a compile error) -
i have following spirit grammar. trying create vector of ast node in struct myresult
using standard push_back(at_c<0>(qi::_val), qi::_1)
getting compile errors (see below).
typedef vector<zls::astnode*> vector_astnode_t; struct myresult { vector_astnode_t turtle_commands; }; boost_fusion_adapt_struct ( myresult, (vector_astnode_t, turtle_commands) ); namespace spirit = boost::spirit; namespace qi = boost::spirit::qi; namespace ascii = boost::spirit::ascii; namespace phoenix = boost::phoenix; struct debugprint { string _name; debugprint( string n ) : _name(n) {} void operator()(int const& i, qi::unused_type, qi::unused_type) const { cout << _name << std::endl; } void operator()(qi::unused_type, qi::unused_type, qi::unused_type) const { cout << _name << std::endl; } // todo: more of these each type }; template <typename iterator> struct lsystem_parser : qi::grammar<iterator, myresult() > { lsystem_parser( zls::context* ctx ) : lsystem_parser::base_type(start) , _ctx( ctx ) { using qi::char_; using qi::float_; using qi::eps; using qi::lit; using qi::_1; using qi::_val; using phoenix::ref; using phoenix::push_back; using phoenix::at_c; float_parameters = '(' >> (float_ >> *(',' >> float_)) >> ')'; /// turtle grammar /// draw_forward = ( char_('f') [ _val = new zls::astdrawforward(_ctx,0)] ) [debugprint("draw_forward")]; move_forward = ( char_('f') [ _val = new zls::astmoveforward(_ctx,0)] ) [debugprint("move_forward")]; turn_left = ( char_('+') [ _val = new zls::astturnleft(_ctx,0)] ) [debugprint("turn_left")]; turn_right = ( char_('-') [ _val = new zls::astturnright(_ctx,0)] ) [debugprint("turn_right")]; push_state = ( char_('[') [ _val = new zls::astpushstate(_ctx)] ) [debugprint("push_state")]; pop_state = ( char_(']') [ _val = new zls::astpopstate(_ctx) ] ) [debugprint("pop_state")]; turtle_commands = (draw_forward | move_forward | turn_left | turn_right | push_state | pop_state); // >>>> causing error <<<<< start = *turtle_commands[ push_back(at_c<0>(qi::_val), qi::_1) ]; } qi::rule< iterator, myresult() > start; qi::rule< iterator, vector<float> > float_parameters; qi::rule< iterator, zls::astnode* > draw_forward; qi::rule< iterator, zls::astnode* > move_forward; qi::rule< iterator, zls::astnode* > turn_left; qi::rule< iterator, zls::astnode* > turn_right; qi::rule< iterator, zls::astnode* > push_state; qi::rule< iterator, zls::astnode* > pop_state; qi::rule< iterator, zls::astnode* > turtle_commands; zls::context* _ctx; };
the following actual errors returned xcode:
container.hpp:492: error: no matching function call 'std::vector<zls::astnode*, std::allocator<zls::astnode*> >::push_back(const boost::fusion::unused_type&)' stl_vector.h:600: note: candidates are: void std::vector<_tp, _alloc>::push_back(const _tp&) [with _tp = zls::astnode*, _alloc = std::allocator<zls::astnode*>] container.hpp:492: error: return-statement value, in function returning 'void'
edit: following revised spirit grammar compiles , works. there few subtle changes note including using phoenix new_
operator , adding following semantic action turtle_commands = ... [_val = _1]
template <typename iterator> struct lsystem_parser : qi::grammar<iterator, vector_astnode_t() > { lsystem_parser( zls::context* ctx ) : lsystem_parser::base_type(start) , _ctx( ctx ) { using qi::char_; using qi::float_; using qi::eps; using qi::lit; using qi::_1; using qi::_val; using phoenix::ref; using phoenix::push_back; using phoenix::at_c; using phoenix::new_; float_parameters = '(' >> (float_ >> *(',' >> float_)) >> ')'; /// turtle grammar /// draw_forward = ( char_('f') [ _val = new_<zls::astdrawforward>(_ctx, (zls::astnode*)0)] ) [debugprint("draw_forward")]; move_forward = ( char_('f') [ _val = new_<zls::astmoveforward>(_ctx, (zls::astnode*)0)] ) [debugprint("move_forward")]; turn_left = ( char_('+') [ _val = new_<zls::astturnleft>(_ctx, (zls::astnode*)0)] ) [debugprint("turn_left")]; turn_right = ( char_('-') [ _val = new_<zls::astturnright>(_ctx, (zls::astnode*)0)] ) [debugprint("turn_right")]; push_state = ( char_('[') [ _val = new_<zls::astpushstate>(_ctx)] ) [debugprint("push_state")]; pop_state = ( char_(']') [ _val = new_<zls::astpopstate>(_ctx) ] ) [debugprint("pop_state")]; turtle_commands = (draw_forward | move_forward | turn_left | turn_right | push_state | pop_state)[_val = _1]; start = *turtle_commands >> qi::eps; } qi::rule< iterator, vector_astnode_t() > start; qi::rule< iterator, vector<float> > float_parameters; qi::rule< iterator, zls::astnode*() > draw_forward; qi::rule< iterator, zls::astnode*() > move_forward; qi::rule< iterator, zls::astnode*() > turn_left; qi::rule< iterator, zls::astnode*() > turn_right; qi::rule< iterator, zls::astnode*() > push_state; qi::rule< iterator, zls::astnode*() > pop_state; qi::rule< iterator, zls::astnode*() > turtle_commands; zls::context* _ctx; };
you can't directly use operator new
inside of semantic actions, use phoenix::new_<> instead.
moreover, attributes rules specified using function notation syntax. therefore, you'll need change rule declarations to:
qi::rule< iterator, zls::astnode*()> draw_forward;
here additional tip. if change start rule to:
start = *turtle_commands >> qi::eps;
you can avoid semantic action alltogether. converting rule (parser) sequence can leverage attribute propagation rules sequences, allowing directly map first element of fusion sequence (the vector_astnode_t turtle_commands
) onto first element of parser sequence (the *turtle_commands
).
i'm not able compile example incomplete, more problems might hidden.
Comments
Post a Comment