Boost :: спирт с тканевыми методами в правиле

Я использую 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);
}

Проблема в том, что духу не нравятся подобные конструкции для правил. Можете ли вы помочь мне в том, как реализовать правило, которое использует этот метод фабрики для возврата этого объекта?

Спасибо!

Ура,
Крис

1

Решение

Предполагая, что фабричные функции на самом деле являются функциями уровня пространства имен:

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

Другие решения

Других решений пока нет …