语法分解问题

时间:2013-11-12 18:15:53

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

当我试图表达语法(Lua的小子集,几乎与 mini_c 相同;不那么复杂)时,我遇到了问题: g ++ 驱动程序提供一段时间后, gas gas 会崩溃(当系统内部消耗大约500MB时,内存消耗为8GB)。我查看Compiler Tutorial并发现,我们应该将复杂的语法分解为较小的语法。

问题是它是强制性的,我们应该让类(由规则集组成)自己的语法(即使它们继承自boost::spirit::qi::grammar)? IOW,我们可以将规则划分为子集并将它们分布在简单类声明之间,作为字段,有意定义(例如,在单独的标头中)并明确地将每个类(在实践中,类模板)实例化为单独的翻译单位,以避免上述崩溃?如果答案是肯定的,那么如何使用宏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 - &gt; statement_level - &gt; function_list_level, - 那么它们必须放在每个(分别)中,或者放在最后链中的类?)?

这个问题的要点是通过简化语法的表达方式来降低编译的复杂性(以及编译时间)。

1 个答案:

答案 0 :(得分:3)

请记住:它只是C ++类。

所以,

  1. 您可以按照自己喜欢的方式将资产拆分为TU。
  2. AFAICT on_error和调试通过引用附加到他们的主题规则,因此您可以将它们放在任何地方
  3. 是的,您可以让类充当规则的“哑”容器。实际上,如果您的迭代器/跳过器没有变化,您可以只使用命名空间:

    //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. 进行优化
  8. 禁用代价高昂的功能:

    • BOOST_SPIRIT_DEBUG
    • 使用BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
    • 避免语义行为
  9. 此外,如果您希望隐藏公共界面中的所有精神,则会出现pimpl / file-static匿名命名空间。