문제

인사말.

나는 문법을 구문 분석하고 AST를 생성 할 때 Boost :: Spirit을 강요하는 방법에 흥미가있었습니다. VariableNode (멤버로 변수 이름이있는), valuenode (멤버로서 값을 가진) 등과 같은 다른 노드를 갖고 싶습니다.

나무 워커를 다룰 때 매우 유용 할 것입니다. 이 경우 우리는 모든 다른 노드 ( "방문자"패턴 적용)를 걷기위한 기본 추상 클래스를 작성하고 의미론 검사 단계, 코드 생성 단계 등을 처리 할 때 확장합니다.

Boost :: Spirit을 통해 우리는 나무에 사용되는 공장을 매개 변수화 할 수 있지만, 그 행동을 조정하는 적절한 방법을 찾을 수 없었습니다.

아이디어, 코드? 미리 감사드립니다.

도움이 되었습니까?

해결책

나는 당신의 질문을 이해하지 못한다. 당신은 이와 같은 것을 의미합니까? :

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

그런 다음 방문자 클래스와 함께 boost :: apply_visitor (boost :: 변형 문서 참조)를 사용하여 원하는 동작을 수행 할 수 있습니다.

다른 팁

귀하의 의견에 답변하려면 (이에 대한 새로운 질문을 시작할 수 있습니다) : 식별자는 Qi :: Symbols-Derived 클래스에 저장되어야하며 키워드는 다른 qi :: 규칙에있을 것입니다.

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

필요한 경우 더 많은 비용을 소비 할 수 있지만 특정 문제가 발생하면 새로운 질문을 시작해야 할 것입니다. 그래서 다른 사람들도 Boost :: Spirit의 초보자 사용자 일뿐 아니라 더 나은 답변을 얻을 수 있기 때문에 도울 수 있습니다.

건배

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top