web-dev-qa-db-ja.com

中置記法からツリーに進むアルゴリズム

次のように、中置方程式から構文ツリーに移動するアルゴリズムを理解しようとしています。

_(1+3)*4+5_

_      +
    *   5
  +   4
 1 3
_

ただし、演​​算子を処理するだけでなく、任意の引数番号を持つ関数も処理する必要があります。

max(1,3,7)*4+5

_      +
    *   5
 max  4
1 3 7
_

ここに私が思いついた一般的なアルゴリズムがあります:

nullの値を含むツリーのルートノードから始めます。式を解析するときにツリー内を移動するポインターがあり、ルートノードを指すようにします。

また、ツリーのいくつかの側面を明確にしておく必要があります。

  1. ノードに挿入するとは、ノードの子の最後に追加することを意味します。
  2. ノードに挿入するとは、ノードの特定のインデックスに追加し、そのインデックスにあるノードを削除して、挿入されたノードに挿入することを意味します。したがって、ノードAにインデックス0で子Bがあり、インデックス__でノードCを注入すると、ノードAには子Cがあり、これに子Bがあります。
  3. インデックスで置換すると、そのインデックスのノードが削除され、代わりに代替ノードが配置されます。したがって、インデックス0で子Aを持つノードBがあり、インデックス0でCを使用して置き換える場合、ノードAと子Cがあります。

さて、ここまでがアルゴリズムです。


インフィックス文字列のすべてのトークンについて:

  • トークンが数値の場合
    • 現在のノードの子として挿入する
  • トークンが引数セパレータである場合
    • 現在のノードの値が関数になるまでツリーをたどります
  • トークンが左括弧の場合
    • 現在のノードの値が関数でない場合は、トークンを子ノードとして挿入し、現在のノードをトークンのノードに設定します。
  • トークンが右括弧の場合
    • 現在のノードが左括弧または関数になるまでトラバースします
    • 現在のノードが左括弧である場合は、最初の子(インデックス0)で置き換えます。これは、最初の子をそのままにして、ツリー構造から括弧ノードを削除することと同じです。
    • 現在のノードの親まで1レベル上に移動します
  • トークンが関数の場合
    • トークンを現在のノードの子ノードとして挿入し、現在のノードを新しく挿入された子ノードに設定します
  • トークンが演算子の場合
    • 現在のノードが左括弧またはルートノードでない場合
      • トラバースする場合
        • 現在のノードはルートにありませんor
        • トークンは右連想であり、トークンの優先順位は現在のノードの優先順位よりも低いor
        • トークンは関連付けられたままで、トークンの優先順位は現在のノードの優先順位よりもまたは等しい未満です
    • 現在のノードの最後のインデックスに新しいノードとしてトークンを挿入する
    • 現在のノードを新しく追加されたトークンの子ノードに設定します

すべてのトークンを通過したら、ルートノードの最初の子を返します。


これをチェックできる既存のアルゴリズムはありますか?これに明らかな問題はありますか?これを使用して接続し、動作するかどうかを確認できる、特に解析が難しい問題はありますか?

3
MirroredFate

コンマを中置演算子として扱います。その後

max(1,3,7)*4+5

なる

        +
       / \
      *   5
     / \
   max  4
    |
    ,
   / \
  ,   7
 / \
1   3

コンマの優先順位は、計算演算子よりも低くなければなりません(+-* /など)。

2
A. I. Breveleri

追跡するものが多すぎて境界のケースが多すぎるため、ある時点で適切なパーサーに卒業する必要があります。 peg.jsへの関数呼び出しの追加 example grammar を取得します。

primary
  = integer
  / "(" additive:additive ")" { return additive; }
  / function_call

function_call
  = [a-z]+ "(" args ")"

args
  = (additive ("," additive)*)?

これは、関数呼び出しや関数呼び出し内にネストされた式などの境界ケースを簡単に処理することに注意してください。

max(3+4,min(6,(1+2)*3))+2
1
Karl Bielefeldt