S表达式解析

我今天早些时候遇到了这个问题 :

示例输入:我遇到乔和吉尔,然后我们去购物
示例输出: [TOP [S [S [NP [PRP I]] [VP [VBD运行] [PP [IN进入] [NP [NNP Joe] [CC和] [NNP Jill]]]]] [CC和] [S [ADVP [RB then]] [NP [PRP we]] [VP [VBD去] [NP [NN shopping]]]]]]

在此处输入图像描述

我打算建议简单地将预期输出(因为它看起来像一个s表达式)解析为一个对象(在我们的例子中是一个树),然后使用简单的LINQ方法来处理它。 但令我惊讶的是,我无法找到C#s-expression解析器。

我唯一能想到的是使用Clojure解析它,因为它编译成clr,我不确定它是一个很好的解决方案。

顺便说一句,我不介意输出dynamic类型的答案。 我在这里找到的答案只是用于反序列化为特定模式。

总结一下我的问题: 我需要在C#中反序列化s表达式 (序列化对于这个问题的未来读者来说会很好)

看起来你需要一个表单的数据结构:

 public class SNode { public String Name { get; set; } private readonly List _Nodes = new List(); public ICollection 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(" )"); } 

以及forms的反序列化:

 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(); 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; } 

但是,如果还没有测试甚至编译过这段代码,那么它或多或少是如何工作的。

我写了一个开源S-Expression解析器,它可以作为S-Expression.NET使用 。 由于它使用OMeta#生成解析器,因此您可以快速使用它来添加新function。