如何从 Boost Spirit X3 词素解析器中获取字符串?
How do you get a string out of a Boost Spirit X3 lexeme parser?
从基于boost::spirit::x3::lexeme
的典型标识符解析器中提取字符串的语义操作的最简单方法是什么?
我认为有可能绕过解压属性的需要,只在输入流中使用迭代器,但显然 x3::_where
并没有按照我的想法去做。
以下结果 output
为空。我希望它包含 "foobar_hello".
namespace x3 = boost::spirit::x3;
using x3::_where;
using x3::lexeme;
using x3::alpha;
auto ctx_to_string = [&](auto& ctx) {
_val(ctx) = std::string(_where(ctx).begin(), _where(ctx).end());
};
x3::rule<class identifier_rule_, std::string> const identifier_rule = "identifier_rule";
auto const identifier_rule_def = lexeme[(x3::alpha | '_') >> *(x3::alnum | '_')][ctx_to_string];
BOOST_SPIRIT_DEFINE(identifier_rule);
int main()
{
std::string input = "foobar_hello";
std::string output;
auto result = x3::parse(input.begin(), input.end(), identifier_rule, output);
}
我是否需要以某种方式从 x3::_attr(ctx)
中的 boost::fusion 对象中提取字符串,还是我做错了什么?
您可以简单地使用自动属性传播,这意味着您不需要语义操作(1)
#include <iostream>
#include <iomanip>
#define BOOST_SPIRIT_X3_DEBUG
#include <boost/spirit/home/x3.hpp>
namespace x3 = boost::spirit::x3;
namespace P {
x3::rule<class identifier_rule_, std::string> const identifier_rule = "identifier_rule";
auto const identifier_rule_def = x3::lexeme[(x3::alpha | x3::char_('_')) >> *(x3::alnum | x3::char_('_'))];
BOOST_SPIRIT_DEFINE(identifier_rule)
}
int main() {
std::string const input = "foobar_hello";
std::string output;
auto result = x3::parse(input.begin(), input.end(), P::identifier_rule, output);
}
版画
<identifier_rule>
<try>foobar_hello</try>
<success></success>
<attributes>[f, o, o, b, a, r, _, h, e, l, l, o]</attributes>
</identifier_rule>
Note I changed '_'
to x3::char_('_')
to capture the underscores (x3::lit
does not capture what it matches)
如果你坚持语义动作,
- 考虑使用
rule<..., std::string, true>
来 也 强制自动属性传播
- 不要假设
_where
指向您希望的结果:http://coliru.stacked-crooked.com/a/336c057dabc86a84
使用x3::raw[]
公开受控源迭代器范围(http://coliru.stacked-crooked.com/a/80a69ae9b99a4c61)
auto ctx_to_string = [](auto& ctx) {
std::cout << "\nSA: '" << _attr(ctx) << "'" << std::endl;
_val(ctx) = std::string(_attr(ctx).begin(), _attr(ctx).end());
};
x3::rule<class identifier_rule_, std::string> const identifier_rule = "identifier_rule";
auto const identifier_rule_def = x3::raw[ lexeme[(x3::alpha | '_') >> *(x3::alnum | '_')] ] [ctx_to_string];
BOOST_SPIRIT_DEFINE(identifier_rule)
Note now the char_('_')
doesn't make a difference anymore
考虑使用内置属性助手:http://coliru.stacked-crooked.com/a/3e3861330494e7c9
auto ctx_to_string = [](auto& ctx) {
using x3::traits::move_to;
move_to(_attr(ctx), _val(ctx));
};
请注意这是如何近似内置属性传播的,尽管它比让 Spirit 管理它要灵活得多
(1) 强制性 link: Boost Spirit: "Semantic actions are evil"?
从基于boost::spirit::x3::lexeme
的典型标识符解析器中提取字符串的语义操作的最简单方法是什么?
我认为有可能绕过解压属性的需要,只在输入流中使用迭代器,但显然 x3::_where
并没有按照我的想法去做。
以下结果 output
为空。我希望它包含 "foobar_hello".
namespace x3 = boost::spirit::x3;
using x3::_where;
using x3::lexeme;
using x3::alpha;
auto ctx_to_string = [&](auto& ctx) {
_val(ctx) = std::string(_where(ctx).begin(), _where(ctx).end());
};
x3::rule<class identifier_rule_, std::string> const identifier_rule = "identifier_rule";
auto const identifier_rule_def = lexeme[(x3::alpha | '_') >> *(x3::alnum | '_')][ctx_to_string];
BOOST_SPIRIT_DEFINE(identifier_rule);
int main()
{
std::string input = "foobar_hello";
std::string output;
auto result = x3::parse(input.begin(), input.end(), identifier_rule, output);
}
我是否需要以某种方式从 x3::_attr(ctx)
中的 boost::fusion 对象中提取字符串,还是我做错了什么?
您可以简单地使用自动属性传播,这意味着您不需要语义操作(1)
#include <iostream>
#include <iomanip>
#define BOOST_SPIRIT_X3_DEBUG
#include <boost/spirit/home/x3.hpp>
namespace x3 = boost::spirit::x3;
namespace P {
x3::rule<class identifier_rule_, std::string> const identifier_rule = "identifier_rule";
auto const identifier_rule_def = x3::lexeme[(x3::alpha | x3::char_('_')) >> *(x3::alnum | x3::char_('_'))];
BOOST_SPIRIT_DEFINE(identifier_rule)
}
int main() {
std::string const input = "foobar_hello";
std::string output;
auto result = x3::parse(input.begin(), input.end(), P::identifier_rule, output);
}
版画
<identifier_rule>
<try>foobar_hello</try>
<success></success>
<attributes>[f, o, o, b, a, r, _, h, e, l, l, o]</attributes>
</identifier_rule>
Note I changed
'_'
tox3::char_('_')
to capture the underscores (x3::lit
does not capture what it matches)
如果你坚持语义动作,
- 考虑使用
rule<..., std::string, true>
来 也 强制自动属性传播 - 不要假设
_where
指向您希望的结果:http://coliru.stacked-crooked.com/a/336c057dabc86a84 使用
x3::raw[]
公开受控源迭代器范围(http://coliru.stacked-crooked.com/a/80a69ae9b99a4c61)auto ctx_to_string = [](auto& ctx) { std::cout << "\nSA: '" << _attr(ctx) << "'" << std::endl; _val(ctx) = std::string(_attr(ctx).begin(), _attr(ctx).end()); }; x3::rule<class identifier_rule_, std::string> const identifier_rule = "identifier_rule"; auto const identifier_rule_def = x3::raw[ lexeme[(x3::alpha | '_') >> *(x3::alnum | '_')] ] [ctx_to_string]; BOOST_SPIRIT_DEFINE(identifier_rule)
Note now the
char_('_')
doesn't make a difference anymore考虑使用内置属性助手:http://coliru.stacked-crooked.com/a/3e3861330494e7c9
auto ctx_to_string = [](auto& ctx) { using x3::traits::move_to; move_to(_attr(ctx), _val(ctx)); };
请注意这是如何近似内置属性传播的,尽管它比让 Spirit 管理它要灵活得多
(1) 强制性 link: Boost Spirit: "Semantic actions are evil"?