2009-10-23 11 views
2

salutations.boost :: spirit et générer différents nœuds

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

ce serait très utile lorsqu'il s'agit de tree-walker. dans ce cas, nous écririons une classe abstraite de base pour marcher tous les différents noeuds (en appliquant le modèle "le visiteur") et l'étendrons en traitant de la phase de vérification sémantique, de la phase de génération de code et des autres. Boost :: spirit nous permet de paramétrer l'usine utilisée pour les arbres, mais j'ai été incapable de trouver un moyen correct d'ajuster son comportement.

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

Répondre

3

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 boost :: documentation variante) avec une classe de visiteur pour faire le comportement que vous voulez.

+0

n1ck, merci beaucoup. oui, vous avez ma bonne question. hmm, j'ai besoin de temps pour jeter un oeil à la version spirit 2.x et à boost :: docs. s'il vous plaît rester en contact. – varnie

+0

Eh bien, agréable d'avoir pu aider. Voici le lien pour le doc le plus à jour pour l'esprit 2.x, je ne sais pas si vous aviez pu l'obtenir mais je l'ai trouvé difficile à trouver et celui sur le site Web de poussée n'était pas la dernière fois que je vérifié: http://svn.boost.org/svn/boost/trunk/libs/spirit/doc/html/index.html. boost :: apply_visitor devrait être relativement facile à utiliser si vous regardez les exemples mais si vous avez besoin d'aide, n'hésitez pas à me le dire. À votre santé. – n1ckp

+0

tout ce boost :: spirit :: qi stuff est complètement nouveau pour moi. J'ai l'ancienne grammaire classique de boost-spirit avec génération d'AST en utilisant les anciennes directives boost (gen_pt_node_d, gen_ast_node_d etc). il est temps pour moi de réécrire ce code avec l'utilisation de boost :: spirit :: qi. J'ai découvert qu'il est possible de générer AST presque à la volée en le décrivant dans la grammaire (avec l'aide de boost :: fusion). – varnie

1

Pour répondre à votre commentaire (vous pourriez vouloir commencer une nouvelle question pour cela): les identifiants devraient probablement être stockés dans une classe dérivée de qi :: symbols et les mots-clés seraient dans vos autres règles qi ::.

Quant à 2) ce serait quelque chose comme ça (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 dépenser plus si vous avez besoin, mais vous devriez probablement commencer une nouvelle question si vous avez des problèmes spécifiques afin que d'autres personnes peuvent aider aussi parce que je suis juste un utilisateur débutant de boost :: spirit et ils pourraient avoir de meilleures réponses.

Salutations

+0

merci pour la réponse. Eh bien, j'ai commencé un autre sujet pour ma question sur le problème des mots-clés/idents. – varnie

Questions connexes