boost::spirit::qi对输出进行重复解析
boost::spirit::qi duplicate parsing on the output
我有一个非常简单的解析器,使用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
我显然做错了什么,但怎么了?
qi::hold
是一种方法,正如@Andrzej 正确提到的那样
我想我有一些观察结果可能会有所帮助,还有一个更好的解决方案。
关键是Spirit在设计时不需要属性的"临时"存储。事实上,它一开始就不能真正假设属性是可复制的。这就是原因所在(想象一下,将所有内容解析为一个std::vector<>,并为每个解析器步骤进行复制?)。
在更重要的层面上,在我看来,这里向后的不是属性处理,而是解析器表达式本身:它无法说明意图,并在处理数字表示时产生了各种复杂性。。。真的不应该。
我的看法是
rule<std::string::iterator, std::string()> zeroTo255, alternatively;
alternatively %= raw [ uint_ [ _pass = (_1 <= 255) ] ];
你看:你让Spirit解析一个数字,实际上只是验证范围,这就是你最初想要做的。
第二件让我觉得很典型的事情是,规则公开了一个std::string
属性,而不是unsigned char
。例如,为什么?
假设这是一个有意识的设计决策,你可以通过明智地使用来实现它
- 负面前瞻(
!parser
)-不影响属性 - 正向前瞻(
&parser
)-不影响属性 - 熟悉
qi::as_string
、qi::raw
、qi::lexeme
和qi::no_skip
- 语义操作(不依赖自动规则)
以下是对原始规则的最小更改的效果:
zeroTo255 = raw [
("25" >> char_("0-5"))
| ('2' >> char_("0-4") >> digit)
| ('1' >> digit >> digit)
| (char_("1-9") >> digit)
| digit
];
这与使用qi::hold
的代码具有大致相同的效果,但没有_hold_ing属性值的性能缺陷。
希望这能有所帮助。
完整示例:Live onhttp://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:t" << std::boolalpha
<< parse(std::begin(input), std::end(input), zeroTo255, output)
<< ": " << output << std::endl;
output.clear();
std::cout << "alternatively:t" << 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
我曾经遇到过类似的问题。这是Spirit中的替代操作符的特殊工作方式。如果您使用附加指令"hold",那么您的示例应该有效。
rule<std::string::iterator, std::string()> zeroTo255
= hold[string("25") >> char_('0', '5')]
| hold[char_('2') >> char_('0', '4') >> digit]
| hold[char_('1') >> repeat[2](digit)]
| hold[char_('1', '9') >> digit] | digit;
有关此行为的详细信息,请参阅此线程。
相关文章:
- 递归函数计算序列中的平方和(并输出过程)
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 请解释"函数1(p1,p2,p3);"的输出
- C++:将控制台输出存储在宏中更好吗
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 为什么我的代码在输出中增加了93天
- 如何从void函数输出字符串
- 输入到文件并输出到另一个文件,并将流文件传递给函数
- AES加密到解密未正确输出
- 如何将c++程序的一些输出传递给shell,以便在shell中使用
- 使用C++程序合并排序没有得到正确的输出
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- C++格式化输出问题
- 将值从二维数组输出到文本文件
- 集合上的输出迭代器:assign和increment迭代器
- 在while循环中输入带有std::cin的字符串后,控制台会输出大量胡言乱语
- boost :: Spirit :: Karma语法:逗号从结构上划定了带有选件属性的输出
- boost::spirit::qi对输出进行重复解析
- 当使用spirit以其他方式解析结构时,会导致输出混乱