Obtenir résultat de la grammaire de l'esprit d'impulsion (push_back Phoenix provoque une erreur de compilation)

StackOverflow https://stackoverflow.com/questions/4322369

  •  29-09-2019
  •  | 
  •  

Question

J'ai la grammaire de l'esprit suivant. Je suis en train de créer un vecteur de nœud AST dans struct myresult en utilisant la norme push_back(at_c<0>(qi::_val), qi::_1) mais je reçois des erreurs de compilation (voir ci-dessous).

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: Voici une grammaire esprit révisée qui compile et travaux. Il y a quelques changements subtils à la note, y compris en utilisant l'opérateur new_ phénix 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;

};
Était-ce utile?

La solution

Vous ne pouvez pas utiliser directement operator new dans des actions sémantiques, l'utilisation Phoenix :: nouveau _ <> à la place.

En outre, les attributs de règles sont exprimées en utilisant la syntaxe de la notation de la fonction. , Vous aurez donc besoin de changer vos déclarations de règle à:

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

Voici un pourboire supplémentaire. Si vous modifiez la règle de départ à:

start = *turtle_commands >> qi::eps;

vous pouvez éviter la alltogether d'action sémantique. En convertissant la règle dans une séquence (parser) on peut tirer parti des règles de propagation d'attribut de séquences, ce qui permet de cartographier directement le premier élément de la séquence de fusion (le vector_astnode_t turtle_commands) sur le premier élément de la séquence d'analyseur (l'*turtle_commands).

Je ne suis pas en mesure de compiler votre exemple car il est incomplet, pourraient être cachés si plus de problèmes.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top