Порядок семантических действий с использованием Духа (со ссылкой на Феникс)

Я создаю парсер для выполнения команд, которые пользователь может вводить в командной строке. Первая часть команды — это модуль, которому она принадлежит, вторая часть — функция вызываемого модуля.

К первому парсеру прикреплено семантическое действие (с boost :: phoenix :: ref ()), которое должно хранить имя модуля в переменной m_moduleName. Ко второму парсеру прикреплено еще одно семантическое действие, которое вызывает функцию printParameters с бывшей переменной в качестве параметра.

#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/home/qi.hpp>
#include <boost/bind.hpp>

#include <iostream>
#include <string>

namespace qi  = boost::spirit::qi;
namespace phoenix = boost::phoenix;void printParameters(const std::string & module, const std::string & command)
{
std::cout << "Module name during parse: " << module << std::endl;
std::cout << "Command name during parse: " << command << std::endl;
}template <typename Iterator>
struct myCommandParser : public qi::grammar<Iterator>
{
myCommandParser() : myCommandParser::base_type(start)
{
start = qi::as_string[+(~qi::char_(' '))][phoenix::ref(m_moduleName) = qi::_1]
>> qi::as_string[+(~qi::char_('\n'))][boost::bind(&printParameters, m_moduleName, ::_1)];
};

qi::rule<Iterator> start;
std::string m_moduleName;
};int main()
{
myCommandParser<std::string::const_iterator> commandGrammar;

commandGrammar.m_moduleName = std::string("initial_default");
std::cout << "Module name before parsing: " << commandGrammar.m_moduleName << std::endl;

std::string str("mod01 cmd02\n");
std::string::const_iterator first = str.begin();
std::string::const_iterator last = str.end();
qi::parse(first, last, commandGrammar);

std::cout << "Module name after parsing: " << commandGrammar.m_moduleName << std::endl;
}

Ожидаемый результат:
Во время первого семантического действия значение m_moduleName должно быть установлено в mod01 который должен быть напечатан во время функции printParameters.

Фактический результат (вывод программы):

Module name before parsing: initial_default
Module name during parse:
Command name during parse:  cmd02
Module name after parsing: mod01

При создании этого минимального примера я заметил, что значение m_moduleName пустой во время выполнения функции разбора, хотя она была предварительно установлена ​​на «initial_default».

Может кто-нибудь объяснить, что именно здесь происходит?

Почему значение пустое, а не mod01?

1

Решение

Вы не можете смешивать заполнители Boost Bind / Phoenix / Lambda / Qi / std.

На самом деле вы не можете использовать Boost Bind внутри семантического действия.

Вы хотите использовать использовать phoenix::bind с qi::_1, Ах, и добавь phoenix::cref() вокруг m_moduleName,

Кроме этого, вы вообще не хотите использовать некрасивые семантические действия:

Упрощенная:

Жить на Колиру

#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;

int main()
{
std::string const str("mod01 cmd02\n");
std::string moduleName, command;
qi::parse(str.begin(), str.end(), +~qi::char_(' ') >> +~qi::char_('\n'), moduleName, command);

std::cout << "Module name after parsing: " << moduleName << "\n";
std::cout << "Command after parsing:     " << command    << "\n";
}

Печать

Module name after parsing: mod01
Command after parsing:      cmd02

Смотрите BOOST_FUSION_ADAPT_STRUCT и boost/fusion/adapted/std_pair.hpp например способы масштабирования / автоматизации

1

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


По вопросам рекламы [email protected]