Question

salutations.

J'ai été intéressant de savoir comment forcer boost :: spirit à produire des nœuds de différentes classes lors de l'analyse syntaxique de la grammaire et de la génération d'AST. disons, je veux avoir différents nœuds tels que VariableNode (qui porte le nom de la variable en tant que membre), ValueNode (qui a la valeur en tant que membre), etc.

cela serait très utile quand on a affaire à un trotteur. dans ce cas, nous écririons une classe abstraite de base pour parcourir tous les différents nœuds (en appliquant le motif "visiteur") et l'étendrions en cas de phase de vérification sémantique, de phase de génération de code, etc.

boost :: spirit nous permet de paramétrer l’usine utilisée pour les arbres, mais j’ai été incapable de trouver un moyen approprié d’ajuster son comportement.

des idées, code? merci d'avance.

Était-ce utile?

La solution

Je ne suis pas sûr de comprendre votre question. Voulez-vous dire quelque chose comme ça? :

typedef boost::variant<VariableNode, ValueNode> AbstractNode;

template <typename Iterator>
struct NodeGrammar: public boost::spirit::qi::grammar<Iterator, AbstractNode(), boost::spirit::ascii::space_type>
{
    NodeGrammar: NodeGrammar::base_type(start)
    {
        start %= variableNode | valueNode >> eps;

        variableNode %= /*something*/;
        valueNode %= /*something*/;
    }

    //start
    boost::spirit::qi::rule<Iterator, AbstractNode(), boost::spirit::ascii::space_type> start;

    boost::spirit::qi::rule<Iterator, VariableNode(), boost::spirit::ascii::space_type> variableNode;
    boost::spirit::qi::rule<Iterator, ValueNode(), boost::spirit::ascii::space_type> valueNode;
};

Vous pouvez ensuite utiliser boost :: apply_visitor (voir la documentation de boost :: variant) avec une classe de visiteurs pour obtenir le comportement souhaité.

Autres conseils

Pour répondre à votre commentaire (vous voudrez peut-être poser une nouvelle question à ce sujet): les identifiants devraient probablement être stockés dans une classe dérivée de qi :: symboles et les mots clés figureraient dans vos autres règles qi ::.

En ce qui concerne 2), cela ressemblerait à ceci (non testé):

class ScriptNodes
{
   //this will  enable fusion_adapt_struct to access your private members
   template < typename, int>
   friend struct boost::fusion::extension::struct_member;

private:
   typdef std::vector<boost::shared_ptr<UserFuncNode> > Nodes
   Nodes nodes;
};

//when using fusion_adapt_struct, try to typedef any type that contain a ,
//since it will confuse the macro (ex std::pair<int, int>)
BOOST_FUSION_ADAPT_STRUCT(
    ScriptNode,
    (ScriptNodes::Nodes, nodes)
)

..

using boost::spirit::qi::grammar;
using boost::spirit::ascii::space_type;

template <typename Iterator>
struct NodeGrammar: public grammar<Iterator, ScriptNodes(), space_type>
{
    NodeGrammar: NodeGrammar::base_type(start)
    {
        using namespace boost::spirit::arg_names;
        using boost::spirit::arg_names::_1;

        //the %= should automatically store the user_func nodes in start
        //for more complex rules you might need to do the push_back manually
        //using phoenix::push_back
        start %= *user_func >> eps;

        //this should parse a double and create a new UserFuncNode with the
        //parsed argument and the result will be assigned in the shared_ptr
        //variable stored in a user_func
        user_func = double_[_val = new UserFuncNode(_1)];
    }

    using boost::spirit::qi::rule;
    using boost::shared_ptr;

    //start
    rule<Iterator, ScriptNodes(), space_type> start;

    rule<Iterator, shared_ptr<UserFuncNode>(), space_type> user_func;
};

Je pourrais probablement en dépenser plus si vous en aviez besoin, mais vous devriez probablement commencer une nouvelle question si vous rencontrez des problèmes spécifiques afin que d'autres personnes puissent aussi vous aider, car je ne suis qu'un utilisateur débutant de boost :: spirit et qu'elles auront peut-être de meilleures réponses.

A bientôt

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