c++ - 语法分解问题

标签 c++ boost boost-spirit boost-spirit-qi

当我尝试表达语法(Lua 的小子集,几乎与 mini_c 相同;不那么复杂)时,我遇到了问题:g++ 驱动程序提供了gasgas 在一段时间后被压碎(当在具有 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++ 类。

所以,

  1. 您可以按照自己喜欢的方式将 Assets 拆分为 TU。
  2. AFAICT on_error 和 debug 通过引用附加到它们的主题规则,因此您可以将它们放在任何地方
  3. 是的,您可以让类充当规则的“哑”容器。事实上,如果您的迭代器/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 (?)

  4. 有利于组合而不是继承(为您的编译器提供更多自由)

  5. 禁用调试信息(-g0)
  6. 尝试优化大小 -Os 或不优化 (-O0)
  7. 禁用昂贵的功能:

    • BOOST_SPIRIT_DEBUG
    • 使用BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
    • 避免语义 Action

此外,pimpl/file-static 匿名命名空间也在那里,以防您希望从您的公共(public)界面中隐藏所有 spirit 。

关于c++ - 语法分解问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19936848/

相关文章:

c++ - 解析时动态切换解析器

c++ - FindResource 按名称查找资源失败

c++ - 双字节交换

c++ - 常量类型定义;在 C 和 C++ 中

c++ - Boost 是否因为不像 Boost 那样有罪?

c++ - Spirit X3,如何在非 ascii 输入上解析失败?

c++ - 为什么 mem_fn 在与 smatch::str 一起使用时编译失败?

c++ - boost 过程 : captured stdout is buffered until size X

linux - 尝试静态链接 Boost

c++ - 将多个内部类型转换为系统级类型