Предположим, у меня есть структура, которую я хочу проанализировать с помощью Spirit Qi, которая определяется как:
struct data_
{
bool export;
std::wstring name;
data_() : export(false) {}
};
Также предположим, что структура была адаптирована для слияния следующим образом:
BOOST_FUSION_ADAPT_STRUCT(
data_,
(bool, export)
(std::wstring, name)
)
И связанное правило:
qi::rule<Iterator, data_(), skipper<Iterator> > rule_data;
rule_data = -lexeme["SpecialText" >> !(alnum | '_')] [ boost::phoenix::at_c<0> = true ] // If this string is found, , set "export" to true
> lexeme["Name" >> !(alnum | '_')] // this is supposed to go into the "name" member
Это компилирует, пока, так хорошо. Тем не менее, «имя» остается пустым сейчас!
По сути, я спрашиваю: учитывая, что «SpecialText» предшествует «Name», как бы я правильно синтезировал логический атрибут для «export», а не строку?
РЕДАКТИРОВАТЬ
После этого я случайно наткнулся на парсер «match []», который, кажется, делает то, что я хочу.
Тем не менее, вопрос все еще существует в общем виде, например, хочу ли я вернуть определенную строку или другой тип данных вместо bool.
По сути, как установить определенный член атрибута struct с помощью семантического действия.
Как установить член структуры.
phx::bind
)Учитывая структуру S
struct S
{
int field1;
std::string field2;
int target_field;
bool field3;
};
Вы можете назначить для поля (например, target_field
) вот так:
rule<It, S()> p = int_ [ phx::bind(&S::target_field, _val) = _1 ];
Теперь вы можете сделать bind
более читабельным, делая что-то вроде:
auto target_field_ = phx::bind(&S::target_field, _val);
p = int_ [ target_field_ = _1 ];
Подтверждение концепции: жить на Колиру
#include "boost/spirit/include/qi.hpp"#include "boost/spirit/include/phoenix.hpp"
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
typedef std::string::const_iterator It;
struct S
{
int field1;
std::string field2;
int target_field;
bool field3;
};
int main()
{
const std::string input("42");
It f(begin(input)), l(end(input));
S instance;
using namespace qi;
rule<It, S()> p = int_ [ phx::bind(&S::target_field, _val) = _1 ];
// or, alternatively:
auto target_field_ = phx::bind(&S::target_field, _val);
p = int_ [ target_field_ = _1 ];
if (parse(f, l, p, instance))
std::cout << "Parsed: " << instance.target_field;
}
Вы можете рассматривать структуру как последовательность слияния, используя приспособление:
#include "boost/fusion/adapted/struct.hpp"
BOOST_FUSION_ADAPT_STRUCT(S, (int, field1)(std::string, field2)(int, target_field)(bool, field3))
Теперь вы можете использовать Феникс ленивый Функции на этих последовательностях в вашем семантическом действии:
rule<It, S()> p = int_ [ phx::at_c<2>(_val) = _1 ];
Я не предпочитаю этот стиль (потому что он «унижает» выразительную структуру до… своего рода кортежа), но он может пригодиться. Жить на Колиру
Других решений пока нет …