我正在使用boost :: spirit为简单的脚本语言构建解析器。在规则中,我想使用对fabric方法的调用来创建一个新对象,该对象是此规则的返回值。
规则是
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);
}
问题是,这种精神不喜欢这些规则的构造。你能帮我解决一下如何实现一个使用这种结构方法返回这个对象的规则吗?
谢谢!
干杯, 克里斯
答案 0 :(得分: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));
}