Frage

Grüße.

Ich habe interessant gewesen, wie boost :: Geist zu zwingen Knoten verschiedener Klassen zu erzeugen, wenn die Grammatik Parsen und AST zu erzeugen. sagen wir, ich will verschiedene Knoten müssen wie VariableNode (der Name der Variablen als Mitglied hat), ValueNode (der Wert als Mitglied hat), etc.

wäre es sehr nützlich sein, wenn sie mit Baum-Walker zu tun. in diesem Fall würden wir eine Basis abstrakte Klasse für das Gehen, all die verschiedenen Knoten (Anwendung „der Besucher“ -Muster) und erweitern sie schreiben, wenn sie mit Semantik überprüft Phase, Codegenerierung Phase und die so zu tun.

boost :: Geist ermöglicht es uns, Fabrik zu parametrieren für Bäume verwendet werden, aber ich habe nicht in der Lage gewesen, eine richtige Art und Weise zu stimmen zu finden sein Verhalten.

Alle Ideen, Code? Vielen Dank im Voraus.

War es hilfreich?

Lösung

Ich bin nicht sicher, ich verstehe Ihre Frage, meinst du so etwas? :

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

Sie können dann mit boost :: apply_visitor mit einer Besucher-Klasse (boost :: variant-Dokumentation), um das gewünschte Verhalten zu tun.

Andere Tipps

Ihren Kommentar beantworten (man könnte eine neue Frage für diesen beginnen soll): Identifikatoren wahrscheinlich in einem Qi gespeichert werden soll :: Symbole abgeleitete Klasse und Keywords in Ihren anderen Qi :: Regeln seien.

Wie bei 2) das so etwas wie diese würde (nicht getestet):

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

Ich könnte wahrscheinlich mehr aufwenden, wenn Sie brauchen, aber Sie sollten wahrscheinlich eine neue Frage beginnen, wenn Sie bestimmen Probleme bekommen, so dass andere Menschen helfen, wie ich nur ein Anfänger Benutzer von boost :: spirit bin und sie könnten bessere Antworten haben.

Prost

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top