Pergunta

saudações.

eu estive interessante em como forçar boost :: espírito para nós produzir de diferentes classes ao analisar a gramática e gerando AST. por exemplo, eu quero ter diferentes nós, como VariableNode (que tem o nome da variável como seu membro), ValueNode (que tem valor como seu membro), etc.

seria muito útil quando se lida com a árvore-walker. neste caso, seria escrever uma classe abstrata base para uma caminhada todos os diferentes nós (aplicando "o visitante" padrão) e estendê-lo ao lidar com a semântica verificação de fase, fase de geração de código e tal.

boost :: espírito nos permite parametrizar fábrica que está sendo usado para árvores, mas eu fui incapaz de encontrar uma maneira adequada para ajustar seu comportamento.

qualquer idéias, código? obrigado antecipadamente.

Foi útil?

Solução

Eu não tenho certeza se entendi sua pergunta, não é algo média como este? :

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;
};

Você pode então usar boost :: apply_visitor (consulte a documentação boost :: variant) com uma classe visitante a fazer o comportamento que você quer.

Outras dicas

Para responder o seu comentário (que você pode querer começar uma nova pergunta para isso): identificadores provavelmente deve ser armazenado em um qi :: símbolos derivadas classe e palavras-chave seria em seus outros qi :: regras.

Quanto 2) isso seria algo como isto (não testado):

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;
};

Eu provavelmente poderia gastar mais se você precisa, mas você provavelmente deve começar uma nova pergunta se você tem questões específicas para que outras pessoas podem ajudar muito como eu sou apenas um usuário iniciante de boost :: espírito e eles podem ter melhores respostas.

Felicidades

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top