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 回答