提升精神范围字符规则创建空字符

boost spirit wide char rule create null char´s

本文关键字:字符 规则 创建 范围      更新时间:2023-10-16

使用此规则

name_valid %= (lexeme[+(boost::spirit::standard_wide::alpha | lit('_'))]);

类型

typedef qi::rule<Iterator, std::wstring()> name_valid;

在调试模式下运行一切正常。name_valid包含正确的字符串。在VC2017中进入发布模式时,我在此类输入上得到了NUL字符

Input  : a_b  
Output : a(NULL)b

我发现我必须像这样重写规则。看不到宽字符操作lit。我在这里错过了什么吗?

name_valid %= +(boost::spirit::standard_wide::alpha | wide::char_(L'_'));

我发现我必须像这样重写规则

好吧,如果目标是将'_'作为名称的一部分进行匹配,那么无论如何您都需要编写它。因为+(alpha | '_')公开一个属性,该属性是所有alpha字符的字符序列,但不公开'_'因为文本不公开属性。

看不到点亮的宽字符操作。

这就是qi::lit(L'_')

我在这里错过了什么吗

我认为正在发生的事情是alpha|'_'合成了一个optional<char>。显然,传播规则非常宽松,optional<char>可以通过其转换为布尔值操作分配给char(导致 NUL 字符)。宽字符与它无关:

住在科里鲁

#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
namespace enc = boost::spirit::standard;
int main() {
std::string const input = "A.B";
auto f = input.begin(), l = input.end();
std::string output;
if (qi::parse(f, l, +(enc::alpha | '.'), output)) {
std::cout << "Parsed: '" << output << "'n";
} else {
std::cout << "Failedn";
}
if (f!=l)
std::cout << "Remaining unparsed: '" << std::string(f,l) << "'n";
}

指纹

00000000: 5061 7273 6564 3a20 2741 0042 270a       Parsed: 'A.B'.

检验假设:

将其拆分为单独的规则使其可见:Live On Coliru

qi::rule<It, char()> c = enc::alpha | '.';
qi::rule<It, std::string()> s = +c;
BOOST_SPIRIT_DEBUG_NODES((s)(c))

指纹

<s>
<try>A.B</try>
<c>
<try>A.B</try>
<success>.B</success>
<attributes>[A]</attributes>
</c>
<c>
<try>.B</try>
<success>B</success>
<attributes>[NUL]</attributes>
</c>
<c>
<try>B</try>
<success></success>
<attributes>[B]</attributes>
</c>
<c>
<try></try>
<fail/>
</c>
<success></success>
<attributes>[[A, NUL, B]]</attributes>
</s>

这突出表明c公开的char确实成为 NUL 字符。然而,以下内容清楚地表明,这并不完全是故意的:Live On Coliru

qi::rule<It, boost::optional<char>()> c = enc::alpha | '.';
qi::rule<It, std::string()> s = +c;
BOOST_SPIRIT_DEBUG_NODES((s)(c))

这将中止断言:

sotest: /home/sehe/custom/boost_1_65_0/boost/optional/optional.hpp:1106: boost::optional::reference_const_type boost::optional<char>::get() const [T = char]: Assertion `this->is_initialized()' failed.

出于好奇:这可以修复它:住在科里鲁

qi::rule<It, std::string()> c = enc::alpha | '.';
qi::rule<It, std::string()> s = +c;

指纹

Parsed: 'AB'

完全符合预期

总结

自动属性传播规则功能强大,但可能令人惊讶。

不要在属性兼容性上玩得又快又松:说出你的意思。就您而言,alpha | char_('_')从概念上讲是唯一应该做您所期望的事情。