Получение результата от грамматики Boost Spirit (phoenix push_back вызывает ошибку компиляции)

У меня есть следующая грамматика духа. Я пытаюсь создать вектор узла AST в struct myresult, используя стандартный push_back(at_c<0>(qi::_val), qi::_1), но получаю ошибки компиляции (см. ниже).

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 for 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);       

        // >>>> THIS IS WHAT IS CAUSING THE 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;

};

Ниже приведены фактические ошибки, возвращаемые XCode:

container.hpp:492: error: no matching function for call to '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 with a value, in function returning 'void'

РЕДАКТИРОВАТЬ: Ниже приведена пересмотренная грамматика духа, которая компилируется и работает. Следует отметить несколько тонких изменений, включая использование оператора phoenix new_ и добавление следующего семантического действия к 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;

};

person zerodog    schedule 01.12.2010    source источник


Ответы (1)


Вы не можете напрямую использовать operator new внутри семантических действий, используйте phoenix::new_‹>.

Кроме того, атрибуты для правил указываются с использованием синтаксиса обозначения функций. Поэтому вам нужно изменить объявления правил на:

qi::rule< Iterator, ZLS::ASTNode*()> draw_forward;

Вот дополнительный совет. Если вы измените правило запуска на:

start = *turtle_commands >> qi::eps;

вы можете полностью избежать семантического действия. Преобразовав правило в последовательность (анализатор), вы можете использовать правила распространения атрибутов для последовательностей, позволяя напрямую отображать первый элемент вашей последовательности слияния (vector_astnode_t turtle_commands) в первый элемент последовательности анализатора (*turtle_commands).

Я не могу скомпилировать ваш пример, так как он неполный, поэтому могут быть скрыты дополнительные проблемы.

person hkaiser    schedule 01.12.2010