> *term >> string(")"); 如何限制递归的最大数量?-6ren">
gpt4 book ai didi

c++ - 如何在boost spirit中设置最大递归

转载 作者:太空狗 更新时间:2023-10-29 21:36:26 25 4
gpt4 key购买 nike

使用boost::spirit,如果我有一个递归规则来解析括号

rule<std::string::iterator, std::string()> term;
term %= string("(") >> *term >> string(")");

如何限制递归的最大数量?例如,如果我尝试解析一百万个嵌套的括号,我会得到一个段错误,因为已经超出了堆栈大小。具体来说,这是一个完整的示例。

#include <iostream>
#include <string>
#include <boost/spirit/include/qi.hpp>

int main(void)
{
using namespace boost::spirit;
using namespace boost::spirit::qi;
const size_t string_size = 1000000;
std::string str;
str.resize(string_size);
for (size_t s=0; s<str.size()/2; ++s)
{
str[s]='(';
str[str.size() - s -1] = ')';
}

rule<std::string::iterator, std::string()> term;
term %= string("(") >> *term >> string(")");
std::string h;
parse(str.begin(), str.end(), term, h);
}

我是用命令编译的

g++ simple.cxx -o simple -std=c++11

如果我将 string_size 设置为 1000 而不是 1000000,它会正常工作。

最佳答案

跟踪 qi::local<> 中的深度或 phx::ref() .

在这种情况下,继承属性可以充当 qi::local 的角色很自然地:

qi::rule<std::string::const_iterator, std::string(size_t depth)> term;
qi::_r1_type _depth;
term %=
qi::eps(_depth < 32) >>
qi::string("(") >> *term(_depth + 1) >> qi::string(")");

term当深度超过 32 时,现在会失败。

完整样本

Live On Coliru

#include <iostream>
#include <string>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;

int main(void) {
for (size_t n : { 2, 4, 8, 16, 32, 64 }) {
auto const str = [&n] {
std::string str;
str.reserve(n);
while (n--) { str.insert(str.begin(), '('); str.append(1, ')'); }
return str;
}();
std::cout << "Input length " << str.length() << "\n";

qi::rule<std::string::const_iterator, std::string(size_t depth)> term;
qi::_r1_type _depth;
term %=
qi::eps(_depth < 32) >>
qi::string("(") >> *term(_depth + 1) >> qi::string(")");

std::string h;

auto f = str.begin(), l = str.end();
bool ok = qi::parse(f, l, term(0u), h);
if (ok)
std::cout << "Ok: " << h << "\n";
else
std::cout << "Fail\n";

if (f != l)
std::cout << "Remaining unparsed: '" << std::string(f, std::min(f + 40, l)) << "'...\n";
}
}

输出:

Input length 4
Ok: (())
Input length 8
Ok: (((())))
Input length 16
Ok: (((((((())))))))
Input length 32
Ok: (((((((((((((((())))))))))))))))
Input length 64
Ok: (((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))
Input length 128
Fail
Remaining unparsed: '(((((((((((((((((((((((((((((((((((((((('...

关于c++ - 如何在boost spirit中设置最大递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40325709/

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