Spirit X3:替代解析器的属性,不是`char`,而是`variant<char, char>`
Spirit X3: attribute of alternative parser, not `char`, but `variant<char, char>`
根据spirit x3 attribute collapsing rule,替代解析器的属性为2
具有相同属性的交替,应该崩溃,即 a: A, b: A --> (a | b): A
,但下面的代码显示它不是,这是错误还是我的错?
这是复合属性规则的spirit x3文档https://www.boost.org/doc/libs/develop/libs/spirit/doc/x3/html/spirit_x3/quick_reference/compound_attribute_rules.html
我有一个代码片段可以重现这个问题
这是代码https://wandbox.org/permlink/7MvN03yiX7ir3esE
和原始代码以防 link 过期
#include <boost/spirit/home/x3.hpp>
#include <iostream>
namespace x3 = boost::spirit::x3;
namespace fusion = boost::fusion;
using x3::_val;
using x3::_attr;
using x3::_where;
using fusion::at_c;
auto const string_def = x3::lexeme["\"" >> *(x3::symbols<char>({ {"\\"", '"'} }) | (x3::print - '\"')) > "\""][([](auto& ctx) {
std::cout << typeid(_attr(ctx)).name();
//should _attr(ctx) be a vector<char>, according to attribute collapsing rule?
})];
int main() {
std::string input = R"__("hello\"world")__";
x3::parse(input.begin(), input.end(), string_def);
}
基本上,代码解析了一个字符串文字,其中包含许多字符 (*
),它可以是除 '"'
之外的字符 (x3::print-'"')
,也可以是转义序列"\\""
表示字符'"'
(x3::symbol<char>...
),两者都有char
的属性,而char | char
应该是char
,而不是variant<char, char>
.
代码的 cout
部分显示的结果类似于 St6vectorIN5boost7variantINS0_6detail7variant13over_sequenceINS0_3mpl6l_itemIN4mpl_5long_ILl2EEEcNS6_INS8_ILl1EEEcNS5_5l_endEEEEEEEJEEESaISF_EE
,在 demangling 之后,它是 vector<variant<over_sequence<...>>>
而 variant<over_sequence<>
基本上是 variant<T...>
的解决方法在 C++ 之前 11 次。
那么代码有什么问题,应该是vector<char>
,而不是vector<variant>
?顺便说一句,我可以自己自定义属性折叠规则吗?
作为@IgorR。评论中提到,语义动作抑制属性传播,我忽略了这一点。所以问题解决了,我可能只需要将其解析为 std::string.
出于某种原因,我需要将其解析为 unique_ptr 对象,因此我需要将解析器分为 rule<StringContent, std::string>
和 rule<StringLiteral, std::unique_ptr<ast::StringLiteral>, true>
,问题已解决
根据spirit x3 attribute collapsing rule,替代解析器的属性为2
具有相同属性的交替,应该崩溃,即 a: A, b: A --> (a | b): A
,但下面的代码显示它不是,这是错误还是我的错?
这是复合属性规则的spirit x3文档https://www.boost.org/doc/libs/develop/libs/spirit/doc/x3/html/spirit_x3/quick_reference/compound_attribute_rules.html
我有一个代码片段可以重现这个问题
这是代码https://wandbox.org/permlink/7MvN03yiX7ir3esE
和原始代码以防 link 过期
#include <boost/spirit/home/x3.hpp>
#include <iostream>
namespace x3 = boost::spirit::x3;
namespace fusion = boost::fusion;
using x3::_val;
using x3::_attr;
using x3::_where;
using fusion::at_c;
auto const string_def = x3::lexeme["\"" >> *(x3::symbols<char>({ {"\\"", '"'} }) | (x3::print - '\"')) > "\""][([](auto& ctx) {
std::cout << typeid(_attr(ctx)).name();
//should _attr(ctx) be a vector<char>, according to attribute collapsing rule?
})];
int main() {
std::string input = R"__("hello\"world")__";
x3::parse(input.begin(), input.end(), string_def);
}
基本上,代码解析了一个字符串文字,其中包含许多字符 (*
),它可以是除 '"'
之外的字符 (x3::print-'"')
,也可以是转义序列"\\""
表示字符'"'
(x3::symbol<char>...
),两者都有char
的属性,而char | char
应该是char
,而不是variant<char, char>
.
代码的 cout
部分显示的结果类似于 St6vectorIN5boost7variantINS0_6detail7variant13over_sequenceINS0_3mpl6l_itemIN4mpl_5long_ILl2EEEcNS6_INS8_ILl1EEEcNS5_5l_endEEEEEEEJEEESaISF_EE
,在 demangling 之后,它是 vector<variant<over_sequence<...>>>
而 variant<over_sequence<>
基本上是 variant<T...>
的解决方法在 C++ 之前 11 次。
那么代码有什么问题,应该是vector<char>
,而不是vector<variant>
?顺便说一句,我可以自己自定义属性折叠规则吗?
作为@IgorR。评论中提到,语义动作抑制属性传播,我忽略了这一点。所以问题解决了,我可能只需要将其解析为 std::string.
出于某种原因,我需要将其解析为 unique_ptr 对象,因此我需要将解析器分为 rule<StringContent, std::string>
和 rule<StringLiteral, std::unique_ptr<ast::StringLiteral>, true>
,问题已解决