4

yacc では、オブジェクトの受け渡しは許可されていません。%union には POD 型のみを含めることができるため、複雑なオブジェクトは新規作成してポインターで渡す必要があります。構文エラーが発生した場合、yacc パーサーは実行を停止するだけで、作成されたすべてのオブジェクトへの参照が失われます。

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

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

別のパーサーを選択するように言わないでください。

4

4 に答える 4

2

私は Yacc が大好きですが、差別的なユニオン スタックには課題があります。

CまたはC++のどちらを使用しているかわかりません。私自身の目的で C++ を生成するように Yacc を変更しましたが、このソリューションは C に適応させることができます。

私の推奨する解決策は、構築されたオブジェクトをスタックの上に渡すのではなく、解析ツリーの下にある所有者にインターフェースを渡すことです。これを行うには、Yacc の外部に独自のスタックを作成します。オブジェクトを割り当てる非ターミナルを呼び出す前に、そのオブジェクトの所有者をこのスタックにプッシュします。

例えば:

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;

    ...
};

式を必要とするものはすべて、IExpressionOwner インターフェイスを実装し、それ自体をスタックにプッシュしてから、式の非ターミナルを呼び出す必要があります。余分なコードがたくさんありますが、オブジェクトの有効期間を制御します。

アップデート

左のオペランドを減らすまで操作がわからないため、式の例は悪いものです。それでも、この手法は多くの場合に機能し、式を少し調整するだけで済みます。

于 2008-09-15T18:26:43.490 に答える
1

プロジェクトに適している場合は、Boehm ガベージ コレクターの使用を検討してください。そうすれば、新しいオブジェクトを自由に割り当てて、コレクターに削除を処理させることができます。もちろん、ガベージ コレクタの使用にはトレードオフがあります。費用と便益を比較検討する必要があります。

于 2008-09-15T17:50:39.533 に答える
-1

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

于 2008-09-16T14:53:08.360 に答える
-1

スマートポインターを使用してください!

または、さらに別のライブラリに依存することに抵抗がある場合は、C++ 標準ライブラリのauto_ptrをいつでも使用できます。

于 2008-09-15T17:50:46.727 に答える