Given semantic actor
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;
};
it seems I'm hitting the fact that the presence of semantic actions inhibit attribute synthesis (or propagation?), ie
const auto norm = x3::rule<struct _, double>{"norm"}
= x3::double_[normalize{100.}];
gives me the value 0.
So I tried forcing attribute propagation by using %=
const auto norm_rule = x3::rule<struct _, double>{"norm"}
%= x3::double_[normalize{100.}];
This gives me the expected parsed value divided by 100.
Then I discovered x3::rule
has a third template argument, bool force_attribute
, and noticed that
const auto norm_rule = x3::rule<struct _, double, true>{"norm"}
= x3::double_[divide{100.}];
Has the wanted result of the value divided by 100.
Experimenting further, I also discovered I could instead define divide::operator()
as follows:
void operator()(ContextType& context)
{
_attr(context) = _val(context) / divisor;
}
This last one seems to strongly couple/condemn the semantic actor to a rule's top level, as it acts on the attribute _attr
of the first rule instead of the value _val
of a parser to which it is attached.
Am I correct in my deduction that
%=
is the same as setting the third x3::rule
template parameter force_attribute
to true? _val
so they work on the attached parser instead of the first rule
encountered in the hierarchy?I understand these may seem lie unrelated questions, but they really are connected as I'm trying to process a parsed number (float) and transform it into an uint8 in several ways. To be totally complete: I have working code (numeric stuff here and the actual thing I'm constructing/parsing here ), but it seems needlessly complex (due to the above it seems I need a rule per type/value transformation, which seems silly.
it seems I'm hitting the fact that the presence of semantic actions inhibit attribute synthesis (or propagation?)
It is so, the behavior was copied from Qi ( qi::rule
docs , How Do Rules Propagate Their Attributes?
).
Relevant code parts: call site , handling .
%=
is the same as setting the thirdx3::rule
template parameterforce_attribute
to true?
Yes, it is not documented, see the code boost/spirit/home/x3/nonterminal/rule.hpp
.
Experimenting further, I also discovered I could instead define
divide::operator()
as follows:void operator()(ContextType& context) { _attr(context) = _val(context) / divisor; }
This last one seems to strongly couple/condemn the semantic actor to a rule's top level, as it acts on the attribute
_attr
of the first rule instead of the value_val
of a parser to which it is attached.
You got it almost right, but swapped them. It should be _val(context) = _attr(context) / divisor
, details are below.
This type of value-processing semantic actions should exclusively work on
_val
so they work on the attached parser instead of the firstrule
encountered in the hierarchy?
The semantic actions documentation describes what _val
and _attr
is:
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)
What they will be in a particular situation depends on make_attribute
/ transform_attribute
traits. By default they will reference to the same value until you have nested rules with different attribute types ( relevant code ).
PS I cannot say anything about the reason why it is so. I see that many Spirit users just use %=
all over the place because intuitively it should be a default, and you can manually disable propagation with omit
directive. Moreover, Qi has some bugs because of this mechanism when you use lazy values on something like repeat
directive ( ticket 13313 ).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.