1

シンプルなスクリプト言語のパーサーを構築するためにboost::spiritを使用しています。ルールでは、ファブリック メソッドへの呼び出しを使用して、このルールの戻り値である新しいオブジェクトを作成したいと考えています。

ルールは

qi::rule<Iterator, NodeHandle(), Skipper>      value;

そして次のように定義されます

value = ( '%' >> +(qi::alpha) >> '%')
        [phoenix::bind(&CreateVarNode, qi::_val, qi::_1)];

実際、これらの「NodeHandles」は、これらの種類のメソッドを介して構築されます

NodeHandle CreateVarNode(std::wstring var)
{
    Node::ptr node(new VarTerminal(var));
    return NodeHandle(node);        
}

問題は、その精神がこの種の規則の構造を好まないことです。このファブリック メソッドを使用してこのオブジェクトを返すルールを実装する方法を教えてください。

ありがとうございました!

乾杯、クリス

4

1 に答える 1

2

ファクトリ関数が実際には名前空間レベルの関数であると仮定します。

namespace Factories
{
    NodeHandle CreateVarNode(std::wstring var)
    {
        Node::ptr node(new VarTerminal(var));
        return NodeHandle(node);        
    }
}

これはうまくいくはずです:

value = ( '%' >> +(qi::alpha) >> '%')
        [qi::_val = phoenix::bind(&Factories::CreateVarNode, qi::_1)];

という名前のクラスの静的メンバーである場合、これは変更されずに機能するはずFactoriesです。少し便利に実装して、次のように書くこともできます。

value = ( '%' >> +(qi::alpha) >> '%') [ createvar ];

これには、Phoenix 関数を使用するための少しの配管が必要です。完全なサンプル:

#define BOOST_SPIRIT_USE_PHOENIX_V3

#include <boost/spirit/include/qi.hpp>
namespace qi  = boost::spirit::qi;
namespace phx = boost::phoenix;

struct VarNode    { VarNode    (std::string        ){ /*todo*/ }  } ;
struct LitNode    { LitNode    (double             ){ /*todo*/ }  } ;
struct Assignment { Assignment (std::string, double){ /*todo*/ }  } ;

struct Node { typedef Node* ptr; };
struct NodeHandle { /*todo*/ };

template <typename ProductNode>
struct NodeFactory
{
    template<typename... T> struct result { typedef NodeHandle type; };

    template<typename... T>
        NodeHandle operator()(T&&... a) const
        {
            Node::ptr node(new ProductNode(std::forward<T>(a)...));
            return NodeHandle(node);
        }
};

int main ()
{
    static const phx::function<NodeFactory<VarNode> >    createvar;
    static const phx::function<NodeFactory<LitNode> >    createliteral;
    static const phx::function<NodeFactory<Assignment> > createassign;

    qi::rule<std::string::const_iterator, NodeHandle()> value 
        = ( '%' >> +(qi::alpha) >> '%') [createvar];

    const std::string input("%a%");
    auto f=begin(input), l=end(input);
    assert(qi::parse(f, l, value));
}
于 2012-12-05T14:13:06.253 に答える