赋予语义参与者
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
设置为true相同吗?_val
上起作用,以便它们在附加的解析器上起作用,而不是在层次结构中遇到的第一个rule
上起作用?我了解这些问题似乎无关紧要,但是当我尝试处理已解析的数字(浮点数)并将其转换为uint8时,它们确实是相关的。要完全完整:我有工作代码(数字内容here和我正在构造/解析的实际内容here),但是它似乎不必要地复杂(由于上述原因,我似乎需要一个规则每个类型/值的转换,这似乎很愚蠢。
答案 0 :(得分:1)
似乎我在想一个事实,即语义动作的存在会抑制属性合成(或传播?)
是这样,该行为是从Qi(qi::rule
docs,How Do Rules Propagate Their Attributes?
)复制而来的。
%=
是否与将第三个x3::rule
模板参数force_attribute
设置为true相同?
是的,没有记录,请参见代码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
上起作用?
semantic actions documentation描述_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
特质。默认情况下,它们将引用相同的值,直到您具有具有不同属性类型(relevant code)的嵌套规则为止。
P.S。我不能说任何原因。我看到许多Spirit用户只是在整个地方都使用%=
,因为从直观上讲它应该是默认设置,并且您可以使用omit
指令手动禁用传播。此外,当您在repeat
指令(ticket 13313)之类的值上使用惰性值时,Qi会由于此机制而存在一些错误。