2010-12-01 4 views
1

J'ai la grammaire d'esprit suivante. J'essaie de créer un vecteur de nœud AST dans struct myresult en utilisant le standard push_back(at_c<0>(qi::_val), qi::_1) mais je reçois des erreurs de compilation (voir ci-dessous).Obtenir le résultat de la grammaire de l'esprit boost (phoenix push_back provoque une erreur de compilation)

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; 

}; 

Voici les erreurs retournées par 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' 

EDIT: Ce qui suit est une grammaire de l'esprit révisé qui compile et travaux. Il y a quelques changements subtils à noter, y compris en utilisant l'opérateur Phoenix new_ et en ajoutant l'action sémantique suivante pour 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; 

}; 

Répondre

2

Vous ne pouvez pas utiliser directement operator new dans des actions sémantiques, utiliser phoenix::new_<> à la place.

De plus, les attributs pour les règles sont spécifiés en utilisant la syntaxe de la notation de fonction. Par conséquent, vous devrez modifier vos déclarations de règles pour:

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

Voici une astuce supplémentaire. Si vous modifiez la règle de démarrage à:

start = *turtle_commands >> qi::eps; 

vous pouvez éviter l'action sémantique ensemble. En convertissant la règle en une séquence (analyseur), vous pouvez exploiter les règles de propagation d'attribut pour les séquences, permettant de mapper directement le premier élément de votre séquence de fusion (vector_astnode_t turtle_commands) sur le premier élément de la séquence analyseur (*turtle_commands).

Je ne peux pas compiler votre exemple car il est incomplet, donc plus de problèmes peuvent être cachés.

Questions connexes