我正在尝试以 boost spirit 编写通用解析器生成器。我想出了以下代码:
auto attr_to_val = [](auto& ctx) { _val(ctx) = boost::fusion::at_c<2>(_attr(ctx)); };
auto parser_gen = [](const std::string a, auto&& p) {
return((boost::spirit::x3::string(a) >> boost::spirit::x3::blank >> p)[attr_to_val]);
};
并尝试像这样使用它:
int a;
auto action = [&a](auto& ctx) { a = _val(ctx); };
auto parser = (parser_gen("aaa", boost::spirit::x3::uint_))[action];
parse(bar.begin(), bar.end(), parser);
但它给出了很多关于无法转换
boost::fusion::deque
的错误至int
.另一方面,当我稍微改变一下时,恕我直言,相当于上面模板代码的扩展:auto pars = (
boost::spirit::x3::string("aaa") >>
boost::spirit::x3::blank >> boost::spirit::x3::uint_)[attr_to_val];
int a;
auto action = [&a](auto& ctx) { a = _val(ctx); };
parse(bar.begin(), bar.end(), pars);
一切都好。我做错了什么,我该怎么做
parser_gen
工作?
最佳答案
x3::lit("aaa")
而不是 x3::string("aaa")
。在 x3 表达式中,裸 "aaa"
将自动被解释为 x3::lit("aaa")
(由于 x3::as_parser
)。 at_c<2>
暗示您也不希望 x3::blank
暴露。为什么不简单地 x3::omit[x3::blank]
?更好的是,考虑使用 skipper ,并隐含。 action
中,您使用的是 x3::_val
,这取决于声明的规则的属性(看不到 x3::rule 吗?)或实际的绑定(bind)引用(您没有向 x3::parse
传递任何内容)。由于您的操作绑定(bind)到解析器参数,因此您似乎想要它的属性,可以改为使用
x3::_attr()
查询。It seems you might be able to do without semantic actions altogether, see below
修复思路:
这结合了以上所有内容:
看到它 Live On Coliru
#include <boost/spirit/home/x3.hpp>
#include <iostream>
namespace x3 = boost::spirit::x3;
int main() {
auto parser_gen = [=](std::string const a, auto&& p) {
return x3::skip(x3::blank)[ x3::lit(a) >> p ];
};
for (std::string const bar : { "aaa 42", "aaa99", }) {
int a;
if (parse(begin(bar), end(bar), parser_gen("aaa", x3::uint_), a)) {
std::cout << "Parsed " << a << "\n";
} else {
std::cout << "Failed\n";
}
}
}
打印
Parsed 42
Parsed 99
label()
助手检查强制空白/ token 边界(请参阅 Stop X3 symbols from matching substrings )看到它 Live On Coliru
namespace {
template <typename P>
auto label_gen(P p) {
return x3::omit[ x3::lexeme[ x3::as_parser(p) >> (&x3::punct | !x3::graph) ] ];
}
template <typename L, typename P> auto parser_gen(L l, P p) {
return x3::skip(x3::blank)[ label_gen(l) >> p ];
}
}
现在打印少一个匹配:
Parsed 42
Failed
奖励:做有用的事情
所以,我猜你想以一种有用的方式组合这些标签/值对中的多个,也许可以解释这些操作。现在,您可以从这个答案中获取一页:Boost Spirit x3: parse into structs。
实际上,我不会在此处复制该示例中的代码,但我认为它可能非常适用于您的用例。
关于c++ - boost::spirit::x3 中的通用解析器生成器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60152454/