提升精神宽char规则创建null char

时间:2017-12-06 08:25:47

标签: c++ boost-spirit

使用此规则

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

类型

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

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

Input  : a_b  
Output : a(NULL)b

我发现我必须像这样重写规则。无法将lit视为宽字符操作。我在这里想念一下吗?

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

1 个答案:

答案 0 :(得分:2)

  

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

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

  

看不到点亮为宽焦操作。

那是qi::lit(L'_')

  

我是否想念这里的东西

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

<强> Mongoose aggregate

#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 << "Failed\n";
    }

    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>

这突出显示char公开的c确实成为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.
  

出于好奇:这解决了这个问题: Live On Coliru

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

打印

Parsed: 'AB'
     

完全符合预期

摘要

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

不要使用属性兼容性来快速松散地玩:说出你的意思。在你的情况下,alpha | char_('_')在概念上是唯一应该按照你的期望做的事情。