当我尝试表达语法(Lua 的小子集,几乎与 mini_c 相同;不那么复杂)时,我遇到了问题:g++ 驱动程序提供了gas 和 gas 在一段时间后被压碎(当在具有 8GB RAM 的系统上达到大约 500MB 的总内存消耗时)。我查看了Compiler Tutorial并发现,我们应该将复杂的语法分解成更小的语法。
问题是它是强制性的,我们应该让类(由规则集组成)本身成为语法(即让它们继承自 boost::spirit::qi::grammar
)? IOW,我们能否将规则划分为子集并将它们作为字段分布在简单类声明之间,以定义(例如,在单独的 header 中)并显式实例化每个类(在实践中,类模板)到单独的翻译单元以避免上述崩溃?如果答案是肯定的,那么如何使用宏 BOOST_SPIRIT_DEBUG_NODES
和构造位置,例如:
using namespace boost::spirit;
qi::on_error< qi::fail >(function_definition_,
error_handler_function(_error_handler)(
"Error! Expecting ", qi::_4, qi::_3));
和
using namespace boost::spirit;
qi::on_success(function_name_,
annotation_function(_error_handler.iters_)(qi::_val, qi::_1));
?
它们应该放在哪里(例如,如果我们有像这样的类链:expression_level --> statement_level --> function_list_level,——那么它们必须(分别)放在每个类中,或者放在最后一个类中链?)?
此类问题的主要目的是通过简化语法的表达方式来降低编译复杂度(以及编译时间)。
最佳答案
记住:它只是 C++ 类。
所以,
- 您可以按照自己喜欢的方式将 Assets 拆分为 TU。
- AFAICT on_error 和 debug 通过引用附加到它们的主题规则,因此您可以将它们放在任何地方
是的,您可以让类充当规则的“哑”容器。事实上,如果您的迭代器/skipper 没有变化,您可以只使用 namespace :
//header namespace G1 { extern const qi::rule<It, attr()> R1; } //cpp namespace G1 { const qi::rule<It, attr()> R1 = qi::eps /* ... */; }
我认为这种方法主要用于 Spirit X3 (?)
有利于组合而不是继承(为您的编译器提供更多自由)
- 禁用调试信息(
-g0
) - 尝试优化大小
-Os
或不优化 (-O0
) 禁用昂贵的功能:
BOOST_SPIRIT_DEBUG
- 使用
BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
- 避免语义 Action
此外,pimpl/file-static 匿名命名空间也在那里,以防您希望从您的公共(public)界面中隐藏所有 spirit 。
关于c++ - 语法分解问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19936848/