4

今日、私はこの質問に出くわしました:

入力例:私はジョーとジルに出くわし、買い物に行きました
出力例: [TOP [S [S [NP [PRP I]]] [VP [VBD ran] [PP [IN into] [NP [NNP Joe] [CC and] [NNP Jill]]]]] [CC and] [S [ADVP [RB then]] [NP [PRP we]] [VP [VBD going] [NP [NN shopping]]]]]]

ここに画像の説明を入力

予想される出力 (S 式のように見えるため) を単純に解析してオブジェクト (この場合はツリー) にし、単純な LINQ メソッドを使用してそれを処理することを提案しようとしていました。しかし、驚いたことに、C# の s-expression パーサーを見つけることができませんでした。

私が考えることができる唯一のことは、clrにコンパイルされるため、Clojureを使用して解析することですが、それが良い解決策であるかどうかはわかりません。

ちなみに、 type の output への回答は構いませんdynamic。ここで見つけた唯一の答えは、特定のスキーマへの逆シリアル化に関するものでした。

私の質問を要約するには: C# で s 式を逆シリアル化する必要があります (シリアル化は、この質問の将来の読者にとって良いでしょう)

4

2 に答える 2

7

次の形式のデータ構造が必要なようです。

public class SNode
{
    public String Name { get; set; }

    private readonly List<SNode> _Nodes = new List<SNode>();
    public ICollection<SNode> Nodes { get { return _Nodes; } }
}

フォームのシリアライザ

public String Serialize(SNode root)
{
    var sb = new StringBuilder();
    Serialize(root, sb);
    return sb.ToString();
}

private void Serialize(SNode node, StringBuilder sb)
{
    sb.Append('(');

    sb.Append(node.Name);

    foreach (var item in node.Nodes)
        Serialize(item, sb);

    sb.Append(" )");
}

そして、次の形式のデシリアライザ:

public SNode Deserialize(String st)
{
    if (String.IsNullOrWhiteSpace(st))
        return null;

    var node = new SNode();

    var nodesPos = String.IndexOf('(');
    var endPos = String.LastIndexOf(')');

    var childrenString = st.SubString(nodesPos, endPos - nodesPos);

    node.Name = st.SubString(1, (nodesPos >= 0 ? nodePos : endPos)).TrimEnd();

    var childStrings = new List<string>();

    int brackets = 0;
    int startPos = nodesPos;
    for (int pos = nodesPos; pos++; pos < endPos)
    {
        if (st[pos] == '(')
            brackets++;
        else if (st[pos] == ')')
        {
            brackets--;

            if (brackets == 0)
            {
                childStrings.Add(st.SubString(startPos, pos - startPos + 1));
                startPos = pos + 1;
            }
        }
    }

    foreach (var child in childStrings)
    {
        var childNode = Deserialize(this, child);
        if (childNode != null)
            node.Nodes.Add(childNode);
    }

    return node;
}

ただし、このコードをテストしたりコンパイルしたりしていない場合は、多かれ少なかれこれが機能する可能性があります。

于 2013-02-03T18:24:22.823 に答える
2

S-Expression.NETとして利用できるオープンソースのS-Expressionパーサーを作成しました。OMeta#を使用してパーサーを生成するため、OMeta#をすばやく操作して新しい機能を追加できます。

于 2013-02-28T21:57:39.010 に答える