7

データベース クエリ コードを生成する式アナライザーを構築しています。それらを左右に分割するのは非常に簡単ですが、括弧を検出してそれに応じてコードを生成する必要があり、これを行う方法がわかりません。

例 [欠陥のあるロジックは無視してください:)]:

a => a.Line2 != "1" && (a.Line2 == "a" || a.Line2 != "b") && !a.Line1.EndsWith("a")

途中で「セット」を検出し、それらのグループ化を維持する必要がありますが、解析中に通常の BinaryExpression と式に違いは見られません (かっこの文字列表現をチェックするのは嫌です)

どんな助けでも大歓迎です。

(私はおそらくC#を使用していることに言及する必要があります)

--編集-- 標準の .Net Expression クラスを使用して式を作成していることに言及しませんでした (System.Linq.Expressions 名前空間)

--Edit2-- テキストをコードに解析しているのではなく、コードをテキストに解析しています。したがって、私の Parser クラスには次のようなメソッドがあります。

void FilterWith<T>(Expression<Func<T, bool>> filterExpression);

これにより、次のようなコードを記述できます。

FilterWith<Customer>(c => c.Name =="asd" && c.Surname == "qwe");

標準の .Net クラスを使用して解析するのは非常に簡単ですが、私の課題はこの式を解析することです。

FilterWith<Customer>(c => c.Name == "asd" && (c.Surname == "qwe" && c.Status == 1) && !c.Disabled)

私の課題は、括弧の間の式を 1 つのセットとして保持することです。.Net クラスは、括弧の部分を他の部分から正しく分割しますが、括弧が原因でセットであることを示しません。

4

2 に答える 2

7

私自身は Expression を使用したことはありませんが、それが他の AST と同じように機能する場合、問題は思ったよりも簡単に解決できます。別のコメンターが指摘したように、すべてのバイナリ式を括弧で囲むだけで、操作の順序の問題について心配する必要はありません。

または、生成している式がそれを含む式よりも優先順位が低いかどうかを確認し、その場合は括弧で囲みます。したがって、このような[* 4 [+ 5 6]]ツリー (ツリー ノードが として再帰的に表される[node left-subtree right-subtree]) がある場合、ツリーを書き出すときに、[+ 4 5]ツリーが操作内に含まれていることがわかります*。これは、操作よりも優先順位が高く+、したがって、その直下のサブツリーよりも必要です。括弧内に配置されます。疑似コードは次のようになります。

function parseBinary(node) {
    if(node.left.operator.precedence < node.operator.precedence)
        write "(" + parseBinary(node.left) + ")"
    else
        write parseBinary(node.left)
    write node.operator
    // and now do the same thing for node.right as you did for node.left above    
}

さまざまな演算子の優先順位の表と、演算子自体を取得して、それが何であるかを調べ、その優先順位を調べる方法が必要です。ただし、その部分を理解できると思います。

于 2011-05-30T17:17:28.690 に答える
0

式アナライザーを構築するときは、まずパーサーが必要であり、そのためにトークナイザーが必要です。

トークナイザーは、式を読み取り、決定された構文のトークン (有効または無効) を生成するコードの一部です。

したがって、パーサーは、トークナイザーを使用して、確立された順序 (左から右、右から左、上から下など、選択した順序) で式を読み取り、式をマップするツリーを作成します。

次に、アナライザーはツリーを式に解釈し、決定的な意味を与えます。

于 2011-05-30T13:53:17.507 に答える