> char_('0', '5')) | (char_('2')-6ren">
gpt4 book ai didi

c++ - boost::spirit::qi 对输出进行重复解析

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:00:01 26 4
gpt4 key购买 nike

我有一个使用 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_stringqi::rawqi::lexemeqi::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 属性值的性能缺陷。

希望这对您有所帮助。

完整示例:在 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:\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

关于c++ - boost::spirit::qi 对输出进行重复解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13869978/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com