3

私は現在、ブースト スピリット X3 を使用して、DSL の式と演算子階層を実装しています。

私のパーサーは意味論的に正しいと思いますが、コンパイルしようとすると、gcc と clang は膨大なメモリ フットプリントを持ち、コンパイルに無限の時間がかかり、「g++: 内部コンパイラ エラー: 強制終了 (プログラム cc1plus) )」。

式パーサーの周りのコードを最小限に抑えようとしましたが、どういうわけかそれほど簡単ではありません

これがデモです。

ここで私が間違っていることを誰かに教えてもらえますか、それともバグですか?

編集:問題はどこかにあると思います:

auto const idx = as<ast::Operation>(helper::idxaccess_op > expression > ']');
auto const func = as<ast::Operation>(helper::func_call_op > expression%',' > ')');
auto const data = as<ast::Operation>(helper::access_op > expression);

auto const func_call_expr_def =
    primary_expr >> *(idx|func|data);

に変更(idx|func|data)すると(idx|func)、それも永久にコンパイルされ、最大 16GB の RAM を使用しますが、gcc はそれをコンパイルでき、パーサーは本来の動作をします。

EDIT II:上記のリンクを見てください。エラーの原因となる私の例があります。

4

2 に答える 2

2

この問題は、テンプレートのインスタンス化の深さと関係があります。を回避しinternal compiler error、許容可能なコンパイル時間を得るために、パーサーにテンプレート ファイアウォールのようなものを実装する必要がありました。これはカスタム パーサーとして実装され、解析式でテンプレート化されていない関数を呼び出します。

struct OptimizedExpressionParser : x3::parser<OptimizedExpressionParser> { 
    using attribute_type = ast::Expression;
    static bool const has_attribute = true;

    //parse fnction, which calls "non-templated"-firewall function
    template <typename Iter, typename Ctx, typename Attribute>
    bool parse(Iter& iFirst, const Iter& iLast, const Ctx& iCtx, x3::unused_type, Attribute& oAttr) const {
      ast::Expression a;
      return parse(iFirst, iLast, iCtx, x3::unused, a);
    }

    //parse fnction, which calls "non-templated"-firewall function
    template <typename Iter, typename Ctx>
    bool parse(Iter& iFirst, const Iter& iLast, const Ctx& iCtx, x3::unused_type, ast::Expression& oAttr) const {
      if (iFirst != iLast) {
        return parse_expression(iFirst, iLast, oAttr);
      }
      return false;
    }
   private:

   //"non-template"- parse function
   //of cause this is a template function, but the parser isnt a template argument
   template <typename Iter>
   bool parse_expression(Iter& iFirst, const Iter& iLast, ast::Expression& oAst) const {
      return x3::parse(iFirst, iLast, expression_impl, oAst);

  } 
  };

このコードexpression_implでは、古い「重い」式パーサーであり、新しい「ファイアウォール」式パーサーは次のとおりです。

auto const expression = OptimizedExpressionParser{};

別のパーサーで式を使用したい場合、または解析のためにパーサーのexpressionオブジェクトを使用するようになりましたOptimizedExpressionParser。これにより、RAM の使用量、コンパイル時間、および結果のバイナリのサイズも減少します (テンプレート ファイアウォールなしでは約 1.6 Gb でした)

正直なところ、私はこの問題を自分で解決したことはありませんでした。アイデアとほとんどのコードはhereから来ています。与えられた例でうまくいくように少し変更しただけです。

于 2016-10-26T00:34:38.233 に答える