2008-09-15 10 views
4

Yaccはオブジェクトを渡すことを許可していません。 %共用体にはPOD型しか含めることができないため、複雑なオブジェクトはnew'dでなければならず、ポインタによって渡されなければなりません。構文エラーが発生すると、yaccパーサーは実行を停止し、作成されたすべてのオブジェクトへの参照が失われます。yaccベースのパーサーでメモリリークを防ぐ最良の方法は何ですか?

私が思いついた唯一の解決策は、すべてのnewオブジェクトが特定の基本クラスを継承し、割り当てられたときにコンテナに追加され、エラーがあればそのコンテナ内のすべてを削除できるということです。

誰かがこの問題を解決するために、より良いyaccのトリックを知っていますか?

別のパーサーを選択するように教えてください。

答えて

2

私はYaccが大好きですが、区別している組合のスタックは挑戦しています。

CまたはC++を使用しているかどうかわかりません。私は自分の目的のためにC++を生成するようにYaccを修正しましたが、この解決策はCに適合させることができます。

私の好みの解決策は、スタックの上に構築されたオブジェクトではなく、これをYaccの外に独自のスタックを作成することで行います。オブジェクトを割り当てる非終端記号を呼び出す前に、そのオブジェクトの所有者をこのスタックにプッシュします。例えば

:式がIExpressionOwnerインターフェイスを実装し、表現非ターミナルを起動する前に、スタックに自分自身をプッシュしていたい

class IExpressionOwner 
{ 
public: 
    virtual ExpressionAdd *newExpressionAdd() = 0; 
    virtual ExpressionSubstract *newExpressionSubtract() = 0; 
    virtual ExpressionMultiply *newExpressionMultiply() = 0; 
    virtual ExpressionDivide *newExpressionDivide() = 0; 
}; 

class ExpressionAdd : public Expression, public IExpressionOwner 
{ 
private: 
    std::auto_ptr<Expression> left; 
    std::auto_ptr<Expression> right; 

public: 
    ExpressionAdd *newExpressionAdd() 
    { 
     ExpressionAdd *newExpression = new ExpressionAdd(); 
     std::auto_ptr<Expression> autoPtr(newExpression); 
     if (left.get() == NULL) 
      left = autoPtr; 
     else 
      right = autoPtr; 
     return newExpression; 
    } 

    ... 
}; 

class Parser 
{ 
private: 
    std::stack<IExpressionOwner *> expressionOwner; 

    ... 
}; 

すべて。余分なコードがたくさんありますが、オブジェクトのライフタイムを制御します。

更新

表現の例は、あなたが左オペランドを削減した後まで、操作がわからないので、悪いものです。それでも、このテクニックは多くの場合に機能し、表現のためにちょっとした調整が必要です。

+0

これは.yppファイルでどのように使用されるかを表示できますか? –

+0

私は、構文解析ツールの外部で並列データ構造を作成するのが最善の解決策であることを認めます。パーサーはグローバル変数にアクセスしなければならないので、パーサーは非リエントラントになりますが、私はそれで生きることができます。 –

1

プロジェクトに合っている場合は、Boehm Garbage collectorの使用を検討してください。そうすれば、新しいオブジェクトを自由に割り当てて、コレクタに削除を処理させることができます。もちろんガベージコレクタの使用にはトレードオフがあります。コストとメリットを勘案しなければなりません。

0

smart pointersを使用してください!

また、別のライブラリによっては不快な場合は、いつでもC++標準ライブラリのauto_ptrを使用できます。

+0

auto_ptrは、渡すことができない複雑なオブジェクトです。 –

1

なぜ異なるパーサを使用しているのですか? Bisonはすぐに利用でき、(少なくともLinuxで)yaccは通常bisonとして実装されています。文法を変更する必要はありません(問題を解決するために%destructorを追加する場合を除く)。

+1

BisonはちょうどGNUのyaccです。同じ質問が適用されます。 –

関連する問題