3

私は、変数が変更されたときに、それらの変数に依存するすべての関数 (およびそれらの関数に依存する関数など) が同時に更新されるように、単純な関数を一緒にバインドできるようにする実験的な関数エバリュエーターを作成しました。これを行う方法は、関数が入力されたときにすぐに関数を評価するのではなく、関数を保存することです。出力値が要求されたときのみ関数を評価し、出力値が要求されるたびに評価します。

例えば:

pi = 3.14159
rad = 5
area = pi * rad * rad
perim = 2 * pi * rad

'pi' と 'rad' を変数 (定数を返す関数) として定義し、'area' と 'perim' を関数として定義します。「pi」または「rad」のいずれかが変化するたびに、「area」と「perim」の結果も同じように変化することを期待しています。同様に、「面積」または「周縁」に依存する関数があれば、それらの結果も変化します。

これはすべて期待どおりに機能しています。ここでの問題は、ユーザーが偶発的または意図的に再帰を導入した場合です。私の文法には論理がありません - それは単なる評価器です - そのため、ユーザーに再帰から「抜け出す」方法を提供することはできません。私はそれがまったく起こらないようにしたいと思っています。つまり、それを検出し、問題のある入力を無効であると宣言する方法が必要です。

例えば:

a = b
b = c
c = a

現在、最後の行を評価すると StackOverflowException が発生します (最初の 2 行は「0」と評価されますが、宣言されていない変数/関数は 0 に等しくなります)。私がやりたいことは、循環論理の状況を検出し、ユーザーがそのようなステートメントを入力することを禁止することです。循環ロジックがどれほど深く隠されているかに関係なく、これを実行したいのですが、どうすればよいかわかりません。

ちなみに、舞台裏では、入力文字列は単純なスキャナーを介してトークンに変換され、次に手書きの再帰降下パーサーを介して抽象構文ツリーに変換され、AST が評価されます。言語は C# ですが、コード ソリューションを探しているわけではありません。ロジックだけで十分です。

注: これは、パーサーとコンパイラーがどのように機能するかを学ぶために私が使用している個人的なプロジェクトであるため、ミッション クリティカルではありません。皆さんが提供できるどんな助けも大歓迎です。=)

編集: 誰かが興味を持っている場合は、私のブログのこの投稿で、私がこれを学ぼうとしている理由と、そこから何を得ているかを説明しています。

4

3 に答える 3

6

私は過去にこれと同様の問題を抱えていました。私の解決策は、構文をチェックするために式を再帰するときに変数名をスタックにプッシュし、再帰レベルを終了するときにそれらをポップすることでした。

各変数名をスタックにプッシュする前に、それが既にそこにあるかどうかを確認します。もしそうなら、これは循環参照でした。循環参照チェーン内の変数の名前を表示することもできました (それらはスタック上にあり、問題のある名前に到達するまで順番にポップオフされる可能性があるため)。

編集:もちろん、これは単一の式の場合でした...あなたの問題については、変数割り当ての巡回グラフがより良い方法です。

于 2008-11-26T20:51:00.603 に答える
2

解決策 (おそらく最善ではない) は、依存関係グラフを作成することです。

関数が追加または変更されるたびに、依存関係グラフのサイクルがチェックされます。

これは短く切ることができます。関数が追加または変更されるたびに、フラグを立てます。評価の結果、フラグが立てられた関数が呼び出された場合は、サイクルが発生しています。

例:

a = b

  • フラグを立てる
  • eval b (見つかりません)
  • フラグを外す

b = c

  • フラグb
  • eval c (見つかりません)
  • b のフラグを外す

c = a

  • 旗 c
  • 評価する
  • 評価b
  • eval c (フラグ付き) -> サイクル、c への変更を破棄!
  • c のフラグを外す
于 2008-11-26T20:51:56.577 に答える
0

回答2のコメントへの返信:

(申し訳ありませんが、openid の作成を台無しにしてしまったので、後で古いものをリンクする必要があります...)

「フラグ」を「プッシュ」に、「フラグ解除」を「ポップ」に切り替えると、ほとんど同じことになります:) スタックを使用する唯一の利点は、サイクルに関する詳細情報を簡単に提供できることです。何その深さ。(エラーメッセージに役立ちます:))

アンドリュー

于 2008-11-26T21:21:04.180 に答える