gpt4 book ai didi

c++ - 使用 bool 属性而不是可选的精神 x3

转载 作者:行者123 更新时间:2023-11-30 05:12:36 25 4
gpt4 key购买 nike

在我想要实现的语法中有一些关键字,其中枚举很重要(将具体关键字的枚举 ID 存储在 ast 的节点内),或者甚至只是存在相同的特定关键字——因此在 bool 上下文中是可选的。我喜欢有一个 self 表达的解析器表达式和 ast 节点,所以我想出了以下(可编译的)解决方案:

#include <iostream>
//#define BOOST_SPIRIT_X3_DEBUG
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

namespace x3 = boost::spirit::x3;

namespace ast {
enum class keyword_token {
UNSPECIFIED, FOO, BAR
};
struct buz {
bool foo;
int dummy;
};
}

BOOST_FUSION_ADAPT_STRUCT( ast::buz, foo, dummy )

namespace boost { namespace spirit { namespace x3 { namespace traits {
template <>
inline void
move_to(ast::keyword_token&& src, bool& dest) {
dest = static_cast<bool>(src);
}
} } } } // boost.spirit.x3.traits


namespace parser {
auto const FOO = x3::rule<struct _, ast::keyword_token> { "FOO" } =
x3::lexeme[ x3::no_case[ "foo" ] >> !(x3::alnum | '_') ]
>> x3::attr(ast::keyword_token::FOO);
auto const buz = x3::rule<struct _, ast::buz> { "buz" } =
-FOO >> x3::int_;
}

int main() {
for(std::string const str: {
"FOO 42",
"42"
}) {
auto iter = str.begin(), end = str.end();
ast::buz attr;
bool r = x3::phrase_parse(iter, end, parser::buz, x3::space, attr);

std::cout << "parse '" << str << "': ";
if (r && iter == end) {
std::cout << "succeeded:\n";
std::cout << (attr.foo ? "FOO " : "") << attr.dummy << "\n";
std::cout << "\n";
} else {
std::cout << "*** failed ***\n";
}
}
return 0;
}

此处 ast 的 buz 节点具有 bool 属性,解析器具有“可选”语法。背后的想法是 bool 是默认可构造的,并且标准保证由预期的 0 aka false 初始化。此外,我有一个 keyword::UNSPECIFIED 的后备解决方案,它(应该,因为我不是 100% 确定枚举类)等于 0 - imo 永远不应该被触发 -在最坏的情况下,x3 的 move_to(...) 特征内的计算结果也为 false。

如预期的那样,两个测试用例的解析阶段都成功运行,但第二个测试用例的属性不是预期的;显然,“ bool 值作为可选”方法无法按预期工作:

<buz>
<try>FOO 42</try>
<FOO>
<try>FOO 42</try>
<success> 42</success>
<attributes>1</attributes>
</FOO>
<success></success>
<attributes>[1, 42]</attributes>
</buz>
parse 'FOO 42': succeeded:
FOO 42

<buz>
<try>42</try>
<FOO>
<try>42</try>
<fail/>
</FOO>
<success></success>
<attributes>[1, 42]</attributes>
</buz>
parse '42': succeeded:
FOO 42

Debug模式显示合成属性[1, 42]。那么,我的考虑是否合理,是否可行,如果是,如何修复它以按预期工作?可能还有另一个问题:没有定义 BOOST_SPIRIT_X3_DEBUG 我收到警告:

warning: 'attr' may be used uninitialized in this function
...
warning: 'attr.ast::buz::dummy' may be used uninitialized in this function

在 cout 行。可能我不理解正确的警告,因为 ast::buz 是默认可构造的,我不想将其作为默认值(false,0)。

蛮力解决方案是这样写:

auto bool_attr = [](auto p) {
return x3::omit[ p ] >> x3::attr(true) | x3::attr(false);
};

并在规则中使用它,但我更喜欢“可选”语法而不是编写 bool_attr(FOO) >> x3::int_etc.

来源也在Coliru .

最佳答案

llonesmiz 明白了 does POD class object initialization require constructor? ;我必须显式编写 ast 节点的构造函数:

struct buz {
bool foo;
int dummy;

buz() : foo{}, dummy{}
{ }
};

比预期的属性要好:

parse 'FOO 42': succeeded:
FOO 42

parse '42': succeeded:
42

有了这个,上面提到的没有定义 BOOST_SPIRIT_X3_DEBUG 的警告也消失了,警告对我来说更有意义......

关于c++ - 使用 bool 属性而不是可选的精神 x3,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44451143/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com