Как семантические действия (с использованием _val и _attr) влияют на определение правил с помощью%= и x3::rule's force_attribute=true?
Данный семантический актер
template<typename ValueType>
class divide
{
public:
divide(ValueType value) : divisor{value} {}
template<typename ContextType>
void operator()(ContextType& context) const
{
_val(context) /= divisor;
}
private:
const ValueType divisor;
};
кажется, я поражаюсь тому, что наличие семантических действий препятствует синтезу атрибута (или распространению?), т.е.
const auto norm = x3::rule<struct _, double>{"norm"}
= x3::double_[normalize{100.}];
дает мне значение 0.
Поэтому я попытался форсировать распространение атрибутов, используя %=
const auto norm_rule = x3::rule<struct _, double>{"norm"}
%= x3::double_[normalize{100.}];
Это дает мне ожидаемое проанализированное значение, деленное на 100.
Тогда я обнаружил x3::rule
имеет третий аргумент шаблона, bool force_attribute
и заметил, что
const auto norm_rule = x3::rule<struct _, double, true>{"norm"}
= x3::double_[divide{100.}];
Имеет желаемый результат значения, разделенного на 100.
Экспериментируя дальше, я также обнаружил, что могу вместо этого определить divide::operator()
следующее:
void operator()(ContextType& context)
{
_attr(context) = _val(context) / divisor;
}
Этот последний, кажется, сильно связывает / осуждает семантического актора на верхний уровень правила, поскольку он действует на атрибут _attr
первого правила вместо значения _val
парсера, к которому он прикреплен.
Правильно ли я в своем выводе, что
%=
так же, как установка третьегоx3::rule
параметр шаблонаforce_attribute
к правде?- Этот тип семантических действий по обработке значений должен работать исключительно на
_val
поэтому они работают на прикрепленном парсере вместо первогоrule
встречались в иерархии?
Я понимаю, что эти вопросы могут показаться несвязанными, но они действительно связаны, так как я пытаюсь обработать проанализированный номер (float) и преобразовать его в uint8 несколькими способами. Чтобы быть полностью законченным: у меня есть рабочий код (числовые данные здесь и фактические вещи, которые я создаю / анализирую здесь), но он кажется излишне сложным (из-за вышеизложенного кажется, что мне нужно правило для преобразования типа / значения, которое кажется глупо.
1 ответ
кажется, я поражаюсь тому факту, что наличие семантических действий препятствует синтезу атрибута (или распространению?)
Это так, поведение было скопировано из Ци (qi::rule
документы, How Do Rules Propagate Their Attributes?
).
Соответствующие части кода: вызов сайта, обработка.
%=
так же, как установка третьегоx3::rule
параметр шаблонаforce_attribute
к правде?
Да, это не задокументировано, см. Код boost/spirit/home/x3/nonterminal/rule.hpp
,
Экспериментируя дальше, я также обнаружил, что могу вместо этого определить
divide::operator()
следующее:void operator()(ContextType& context) { _attr(context) = _val(context) / divisor; }
Этот последний, кажется, сильно связывает / осуждает семантического актора на верхний уровень правила, поскольку он действует на атрибут
_attr
первого правила вместо значения_val
парсера, к которому он прикреплен.
Вы поняли это почти правильно, но поменялись местами. Так должно быть _val(context) = _attr(context) / divisor
, подробности ниже.
Этот тип семантических действий по обработке значений должен работать исключительно на
_val
поэтому они работают на прикрепленном парсере вместо первогоrule
встречались в иерархии?
Документация по семантическим действиям описывает, что _val
а также _attr
является:
Function Description Example
-------- -------------------------------------------------- -----------------------
_val A reference to the attribute of the innermost rule _val(ctx) = "Gotya!"
that directly or indirectly invokes the parser p
_attr A reference to the attribute of the parser p _val(ctx) += _attr(ctx)
Чем они будут в конкретной ситуации, зависит от make_attribute
/ transform_attribute
черты. По умолчанию они будут ссылаться на одно и то же значение, пока у вас не будут вложенные правила с разными типами атрибутов ( соответствующий код).
PS Я не могу ничего сказать о причине, почему это так. Я вижу, что многие пользователи Spirit просто используют %=
повсюду, потому что интуитивно это должно быть по умолчанию, и вы можете вручную отключить распространение с помощью omit
директивы. Более того, у Qi есть некоторые ошибки из-за этого механизма, когда вы используете ленивые значения для чего-то вроде repeat
директива ( билет 13313).