[英]Generic parser generator in boost::spirit::x3
I am trying to write generic parser generator in boost spirit.我正在尝试以提升精神编写通用解析器生成器。 I have come up with following code:
我想出了以下代码:
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]);
};
and tried to use it like this:并尝试像这样使用它:
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);
but it gives a lot of errors about being unable to convert boost::fusion::deque
to int
.但它给出了很多关于无法将
boost::fusion::deque
转换为int
。 On the other hand when I change it a bit like that, which is IMHO equivalent to the expansion of above template code:另一方面,当我稍微改变它时,恕我直言,相当于上述模板代码的扩展:
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);
It is all fine.一切都很好。 What am I doing wrong and how can I make
parser_gen
work?我做错了什么,我怎样才能让
parser_gen
工作?
You don't need to expose all attributes, simplifying the attribute types considerably.您不需要公开所有属性,从而大大简化了属性类型。
For matching a string literal without exposing it as a key (which, apparently, you don't want anyways, because you're ignoring it in the semantic action), use x3::lit("aaa")
instead of x3::string("aaa")
.要匹配字符串文字而不将其作为键公开(显然,您无论如何都不想要,因为您在语义操作中忽略了它),请使用
x3::lit("aaa")
而不是x3::string("aaa")
。 In x3 expression, a bare "aaa"
will automatically be interpreted as x3::lit("aaa")
(due to x3::as_parser
).在 x3 表达式中,一个裸
"aaa"
将自动解释为x3::lit("aaa")
(由于x3::as_parser
)。
What's more, you are addressing at_c<2>
implying that you didn't want x3::blank
exposed either.更重要的是,您正在解决
at_c<2>
暗示您也不希望x3::blank
暴露。 Why not simply x3::omit[x3::blank]
?为什么不简单地
x3::omit[x3::blank]
? Better yet, consider the use of a skipper, and have that implicit.更好的是,考虑使用船长,并隐含地使用它。
In action
you are using x3::_val
, which depends on the declared rule's attribute (there is no x3::rule in sight?) OR the actual bound reference (you don't pass anything to x3::parse
).在
action
使用的是x3::_val
,这取决于申报规则的属性(没有X3 ::在望规则吗?)或实际界限参考(你没有通过什么x3::parse
)。
Since your action binds to the parser argument it seems you wanted its attribute, which can be queried with x3::_attr()
instead.由于您的操作绑定到解析器参数,因此您似乎想要它的属性,可以使用
x3::_attr()
来查询。
It seems you might be able to do without semantic actions altogether, see below
似乎您可以完全不用语义操作,请参见下文
This combines all the above:这结合了以上所有内容:
See it Live On Coliru 在 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";
}
}
}
Prints印刷
Parsed 42
Parsed 99
label()
helper that checks for mandatory whitespace/token boundary (see Stop X3 symbols from matching substrings )label()
帮助程序检查强制性空格/令牌边界(请参阅匹配子字符串中的停止 X3 符号) See it Live On Coliru 在 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 ];
}
}
Now prints one less match:现在少打印一个匹配项:
Parsed 42
Failed
So, my guess is you wanted to combine multiple of these label/value pairs in a useful fashion, perhaps explaining the actions.所以,我的猜测是你想以一种有用的方式组合多个这些标签/值对,也许可以解释这些动作。 Now, you could take a page from this answer: Boost Spirit x3: parse into structs .
现在,您可以从这个答案中获取一页: Boost Spirit x3: parse into structs 。
Actually, I will refrain from reproducing the code from that example here, but I think it might apply to your use case very well.实际上,我不会在此处复制该示例中的代码,但我认为它可能非常适用于您的用例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.