Сцепление семантических действий
У меня проблемы с цепочкой семантических действий.
Хочу разобрать процент (X%
с X
действительное число) и вернуть его значение в виде числа с плавающей точкой от 0 до 1. Я также хочу потерпеть неудачу, если процент выше, чем 100%.
В настоящее время у меня есть два почти тривиально простых правила и несколько простых семантических действий:
const auto ensure_normalized = [](auto& context)
{
const auto& value = _attr(context);
_pass(context) = value >= 0 && value <= 1;
_val(context) = _attr(context);
};
template<typename T, typename ContextType>
void multiply_by(T multiplier, ContextType& context)
{
using value_type = std::remove_reference_t<decltype(_val(context))>;
using attribute_type = std::remove_reference_t<decltype(_attr(context))>;
_val(context) = value_type(_attr(context) * attribute_type(multiplier));
}
constexpr auto divide_by_100 = [](auto& context) { multiply_by(.01f, context); };
const auto percentage = rule<struct percentage, float>{"percentage"}
= (float_ >> '%')[divide_by_100];
const auto normalized_percentage = rule<struct normalized_percentage, float>{"normalized_percentage"}
= percentage[ensure_normalized];
Это работает для всего, что я бросил в это так, как я ожидаю. Дело в том, я не чувствую, что делаю это The Right Way
(т.е. я не думаю, что я использую Boost.Spirit.X3, как предполагалось). Особенно взрыв rule
Это кажется смешным.
Если я попытаюсь применить ensure_normalized
семантическое действие непосредственно к первому правилу, например
const auto normalized_percentage = rule<struct normalized_percentage, float>{"normalized_percentage"}
= ((float_ >> '%')[divide_by_100])[ensure_normalized];
Я получаю мусор. Также кажется, что назначение в ensure_normalized
это что-то вроде хака. Я просто не вижу, как еще сказать X3, что делать.
Код на колиру.