boost::spirit::x3 中的通用解析器生成器
Generic parser generator in boost::spirit::x3
我正在尝试编写通用解析器生成器。我想出了以下代码:
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]
?更好的是,考虑使用船长,并隐含它。 -
在
action
中,您使用的是x3::_val
,这取决于声明的规则的属性(看不到 x3::rule?或实际的绑定引用(您不会向x3::parse
传递任何内容(。由于您的操作绑定到解析器参数,因此您似乎想要它的属性,可以用
x3::_attr()
来查询。似乎你可以完全不用语义操作,见下文
修复想法:
这结合了上述所有内容:
使用船长- (请参阅提升精神船长问题(
- 简化文字
在科里鲁现场观看
#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 << "Failedn";
}
}
}
指纹
Parsed 42
Parsed 99
- 使用检查强制空格/标记边界的
label()
帮助程序(请参阅从匹配的子字符串中停止 X3 符号(
在科里鲁现场观看
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:解析成结构。
实际上,我将避免在此处重现该示例中的代码,但我认为它可能非常适合您的用例。
相关文章:
- boost::spirit::x3 中的通用解析器生成器
- 如何处理Boost Spirit X3导致Visual Studio 2019 "static initialization order fiasco"?
- Boost Spirit X3:将(一些)空格解析为枚举
- Boost Spirit x3 条件(三元)运算符解析器
- 你如何从 Boost Spirit X3 词法解析器中获取字符串?
- 将 Boost.Spirit.X3 解析器拆分为多个 TU
- boost::spirit::x3 中的简单字符串解析器不起作用
- 自定义预期失败的完整错误消息(boost::spirit::x3)
- (如何)我可以在不安装完整的提升库的情况下使用 boost::spirit X3 吗?
- 如何在 Spirit X3 中正确指定锚定条件?
- Spirit.X3 与 lambda 返回不同的解析器类型
- Boost.Spirit X3 替代操作员
- Spirit X3:自定义数字解析器在结果中产生意外的前导零
- Boost.Spirit X3 解析器"no type named type in(...)"
- boost::spirit::x3 phrase_parse 在进入 Vector 之前进行算术运算
- 使用 Spirit x3,如何控制在每个不同的输入上调用哪个解析器?
- Spirit X3, ascii::cntrl why disparity with std::iscntrl?
- 在 Spirit X3 中使用布尔属性而不是可选属性
- Spirit X3,如何在非ASCII输入上失败
- 如何使用 Boost Spirit x3 编写具有两个后操作数语法的二进制运算符?