Boost.Spirit.Qi: 定义太多解析器的组合达到模板实例化限制
Boost.Spirit.Qi: Defining a combination of too many parsers reaches template instantiation limit
这是一个有效(且可编译)的解析器组合:
lit("foo") | lit("bar") | lit("baz")
但是当涉及到大约 200-400 二进制连接时,它失败了。
这是示例错误输出:
fatal error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
当然可以。我爱你,编译器。
实际错误是这样的:
/usr/local/include/boost/proto/detail/preprocessed/matches_.hpp: In instantiation of ‘struct boost::proto::detail::matches_<boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or,
...bitwise_or
永远持续下去。
我很确定这就是表达式模板的性质。
引用 Spirit 的文档:
Spirit pushes the C++ compiler hard.
哈哈。
那么...是否有一种有效且足够简单的方法来实现逻辑上等效的组合解析器?
我想到了著名的 Nabialek 技巧,但它不适合;它用于延迟缓存 k-v 对,而不是用于生成解析器本身(如果我的理解是正确的)。
只需使用一个symbols<>
。如果要传播匹配的输入,请使用 raw[]
这是一个解析 并匹配 来自 rfc3092 的所有关键字的示例:
#include <boost/spirit/include/qi.hpp>
#include <cassert>
namespace qi = boost::spirit::qi;
using It = std::string::const_iterator;
int main() {
qi::symbols<char> much;
for (auto kw : {"bar", "baz", "qux", "quux", "corge", "grault", "garply", "waldo", "fred", "plugh", "xyzzy", "thud"})
much.add(kw);
qi::rule<It, std::string()> match_much = qi::raw [ much ];
much.for_each([&](std::string const& kw, qi::unused_type) {
std::string matched;
assert(qi::parse(kw.begin(), kw.end(), match_much, matched));
assert(kw == matched);
});
}
这是一个有效(且可编译)的解析器组合:
lit("foo") | lit("bar") | lit("baz")
但是当涉及到大约 200-400 二进制连接时,它失败了。
这是示例错误输出:
fatal error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
当然可以。我爱你,编译器。
实际错误是这样的:
/usr/local/include/boost/proto/detail/preprocessed/matches_.hpp: In instantiation of ‘struct boost::proto::detail::matches_<boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or,
...bitwise_or
永远持续下去。
我很确定这就是表达式模板的性质。
引用 Spirit 的文档:
Spirit pushes the C++ compiler hard.
哈哈。
那么...是否有一种有效且足够简单的方法来实现逻辑上等效的组合解析器?
我想到了著名的 Nabialek 技巧,但它不适合;它用于延迟缓存 k-v 对,而不是用于生成解析器本身(如果我的理解是正确的)。
只需使用一个symbols<>
。如果要传播匹配的输入,请使用 raw[]
这是一个解析 并匹配 来自 rfc3092 的所有关键字的示例:
#include <boost/spirit/include/qi.hpp>
#include <cassert>
namespace qi = boost::spirit::qi;
using It = std::string::const_iterator;
int main() {
qi::symbols<char> much;
for (auto kw : {"bar", "baz", "qux", "quux", "corge", "grault", "garply", "waldo", "fred", "plugh", "xyzzy", "thud"})
much.add(kw);
qi::rule<It, std::string()> match_much = qi::raw [ much ];
much.for_each([&](std::string const& kw, qi::unused_type) {
std::string matched;
assert(qi::parse(kw.begin(), kw.end(), match_much, matched));
assert(kw == matched);
});
}