سؤال

والتحيات.

ولقد كنت مثيرة للاهتمام في كيفية فرض دفعة :: روح لإنتاج العقد من فئات مختلفة عند تحليل قواعد اللغة وتوليد AST. ويقول، أريد أن يكون العقد مختلفة مثل VariableNode (التي لديها اسم المتغير كما الأعضاء فيها)، ValueNode (التي لديها قيمة بصفتها عضوا)، وغيرها.

وسيكون من المفيد جدا عند التعامل مع شجرة ووكر. في هذه الحالة كنا كتابة فئة مجردة الأساس للمشي كافة العقد مختلفة (تطبيق "الزائر" نمط) وتمديده عند التعامل مع دلالات فحص المرحلة، مرحلة الجيل رمز ومثل هذه.

ودفعة :: روح يسمح لنا بالحدود مصنع تستخدم لالأشجار، ولكن لقد كنت غير قادر على العثور على الطريقة الصحيحة لضبط سلوكه.

وأية أفكار أو مدونة؟ يرجع الفضل في ذلك مسبقا.

هل كانت مفيدة؟

المحلول

وأنا لست متأكدا من أنني أفهم سؤالك، هل تعني شيئا مثل هذا؟ :

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

ويمكنك بعد ذلك استخدام دفعة :: apply_visitor (راجع وثائق دفعة :: البديل) مع فئة الزوار للقيام بهذا السلوك الذي تريده.

نصائح أخرى

للرد على تعليق (قد ترغب في بدء سؤالا جديدا لهذا): ربما يجب أن يتم تخزين معرفات في تشي :: أن رموز المستمدة من الدرجة والكلمات الرئيسية ستكون في تشي الأخرى الخاصة بك :: القواعد.

وأما بالنسبة لل2) هذا من شأنه أن يكون شيئا مثل هذا (لم تختبر):

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

وأنا ربما يمكن أن تنفق أكثر إذا كنت في حاجة ولكن يجب أن تبدأ على الأرجح سؤال جديد إذا كنت حصلت على قضايا محددة من الأشخاص الآخرين يمكن أن تساعد أيضا، حيث أنا مجرد مستخدم المبتدئ من دفعة :: روح وقد يكون لديهم إجابات أفضل.

وهتاف

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top