我在链接语义动作时遇到麻烦。
我想解析一个百分比(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该怎么做。
代码在coliru上。