boost::spirit::qi duplicate parsing on the output(boost::spirit::qi 重复解析输出)
问题描述
我有一个使用 Boost::Spirit 的非常简单的解析器:
I have this very simple parser using Boost::Spirit:
rule<std::string::iterator, std::string()> zeroTo255 = (string("25") >> char_('0', '5'))
| (char_('2') >> char_('0', '4') >> digit)
| (char_('1') >> repeat[2](digit))
| (char_('1', '9') >> digit) | digit;
当我尝试解析时
std::string o{"1"};
std::string s;
parse(o.begin(), o.end(), zeroTo255, s);
std::cout << o << ": " << s << std::endl;
我有作为输出
1: 111
我显然做错了什么,但是什么?
I'm obviously doing something wrong, but what?
推荐答案
qi::hold 是一种解决方案,正如@Andrzej 正确提到的
qi::hold is one way about it, as correctly mentioned by @Andrzej
我想我有一些观察可能会有所帮助,以及更好的解决方案.
I think I have a few observations that might help, as well as a better solution.
关键是 Spirit 设计上不需要属性的临时"存储.事实上,它不能真正假设该属性首先是可复制的.这就是这里的原因(想象一下将所有内容解析为单个 std::vector<> 并为每个解析器步骤复制?).
The point is that Spirit will not require 'temp' storage for attributes by design. In fact, it can't really assume the attribute be copyable in the first place. This is the reason here (imagine parsing everything into a single std::vector<> and copying for each parser step?).
在更重要的层面上,在我看来,这里倒退的不是属性处理,而是解析器表达式本身:它没有说明意图,并导致各种处理数字表示的复杂性当......真的不应该.
On a more essential level, it looks to me as if it is not the attribute handling that is backwards here, but the parser expression itself: It fails to state the intent, and incurs all kinds of complexity dealing with number representations when... really it shouldn't.
我的看法是
rule<std::string::iterator, std::string()> zeroTo255, alternatively;
alternatively %= raw [ uint_ [ _pass = (_1 <= 255) ] ];
你看:你让 Spirit 解析一个数字,实际上只是验证范围,这就是你首先想要做的.
You see: you let Spirit parse a number, and indeed just verify the range, which is what you wanted to do in the first place.
让我印象深刻的第二件事是规则公开了一个 std::string 属性,而不是 unsigned char 例如这是为什么?
The second thing that strikes me as a-typical, is the fact that the rule exposes a std::string attribute, instead of unsigned char e.g. Why is that?
假设这是一个有意识的设计决定,您可以通过明智地使用
Assuming this was a conscious design decision, you can have it your way by judicious use of
- 否定前瞻 (
!parser) - 不影响属性 - 正向前瞻 (
&parser) - 不影响属性 - 熟悉
qi::as_string、qi::raw、qi::lexeme和qi::no_skip - 语义动作(不要依赖自动规则)
- negative lookahead (
!parser) - which doesn't affect attributes - positive lookahead (
&parser) - which doesn't affect attributes - Get acquainted with
qi::as_string,qi::raw,qi::lexemeandqi::no_skip - semantic actions (don't rely on automatic rules)
以下是对您的原始规则进行的最小改动本可以起作用:
Here's what minimal change to your original rule would have worked:
zeroTo255 = raw [
("25" >> char_("0-5"))
| ('2' >> char_("0-4") >> digit)
| ('1' >> digit >> digit)
| (char_("1-9") >> digit)
| digit
];
这与使用 qi::hold 的代码效果大致相同,但不是 _hold_ing 属性值的性能缺陷.
This has roughly the same effect as the code using qi::hold but not the performance drawback of _hold_ing attribute values.
希望这会有所帮助.
完整示例:http://liveworkspace.org/code/4v4CQW$0:
Full sample: Live on http://liveworkspace.org/code/4v4CQW$0:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
int main()
{
using namespace qi;
rule<std::string::iterator, std::string()> zeroTo255, alternatively;
zeroTo255 = raw [
("25" >> char_("0-5"))
| ('2' >> char_("0-4") >> digit)
| ('1' >> digit >> digit)
| (char_("1-9") >> digit)
| digit
];
alternatively %= raw [ uint_ [ _pass = (_1 <= 255) ] ];
for (auto& input : std::vector<std::string> { "255", "249", "178", "30", "4" })
{
std::string output;
std::cout << "zeroTo255: " << std::boolalpha
<< parse(std::begin(input), std::end(input), zeroTo255, output)
<< ": " << output << std::endl;
output.clear();
std::cout << "alternatively: " << std::boolalpha
<< parse(std::begin(input), std::end(input), alternatively, output)
<< ": " << output << std::endl;
}
}
输出
zeroTo255: true: 255
alternatively: true: 255
zeroTo255: true: 249
alternatively: true: 249
zeroTo255: true: 178
alternatively: true: 178
zeroTo255: true: 30
alternatively: true: 30
zeroTo255: true: 4
alternatively: true: 4
这篇关于boost::spirit::qi 重复解析输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:boost::spirit::qi 重复解析输出
基础教程推荐
- 我有静态或动态 boost 库吗? 2021-01-01
- 常量变量在标题中不起作用 2021-01-01
- 在 C++ 中计算滚动/移动平均值 2021-01-01
- C++结构和函数声明。为什么它不能编译? 2022-11-07
- 这个宏可以转换成函数吗? 2022-01-01
- 如何将 std::pair 的排序 std::list 转换为 std::map 2022-01-01
- 如何在 C++ 中初始化静态常量成员? 2022-01-01
- 静态库、静态链接动态库和动态链接动态库的 .lib 文件里面是什么? 2021-01-01
- 如何检查GTK+3.0中的小部件类型? 2022-11-30
- 如何通过C程序打开命令提示符Cmd 2022-12-09
