184 lines
4.8 KiB
C#
184 lines
4.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
namespace SExpression
|
|
{
|
|
public partial class SExpression
|
|
{
|
|
public const string ErrorStrNotValidFormat = "Not valid format.";
|
|
}
|
|
public partial class SExpression : ISExpression
|
|
{
|
|
public String Serialize(SNode root)
|
|
{
|
|
if (root == null)
|
|
{
|
|
throw new ArgumentNullException();
|
|
}
|
|
var sb = new StringBuilder();
|
|
Serialize(root, sb);
|
|
return sb.ToString();
|
|
}
|
|
private void Serialize(SNode node, StringBuilder sb)
|
|
{
|
|
sb.Append('(');
|
|
|
|
if (node.Items.Count > 0)
|
|
{
|
|
int x = 0;
|
|
foreach (var item in node.Items)
|
|
{
|
|
if (x>0)
|
|
{
|
|
sb.Append(' ');
|
|
}
|
|
else
|
|
{
|
|
x++;
|
|
}
|
|
if (item.Items.Count > 0)
|
|
{
|
|
Serialize(item, sb);
|
|
}
|
|
else
|
|
{
|
|
SerializeItem(item, sb);
|
|
}
|
|
}
|
|
}
|
|
|
|
sb.Append(')');
|
|
}
|
|
private void SerializeItem(SNode node, StringBuilder sb)
|
|
{
|
|
if (node.Name == null)
|
|
{
|
|
sb.Append("()");
|
|
return;
|
|
}
|
|
node.Name = node.Name.Replace("\"", "\\\"");
|
|
if (node.Name.IndexOfAny(new char[] { ' ', '"', '(', ')' }) != -1 || node.Name == string.Empty)
|
|
{
|
|
sb.Append('"').Append(node.Name).Append('"');
|
|
return;
|
|
}
|
|
sb.Append(node.Name);
|
|
}
|
|
}
|
|
public partial class SExpression
|
|
{
|
|
public SNode Deserialize(string st)
|
|
{
|
|
if (st==null)
|
|
{
|
|
return null;
|
|
}
|
|
st = st.Trim();
|
|
if (string.IsNullOrEmpty(st))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var begin = st.IndexOf('(');
|
|
if (begin != 0)
|
|
{
|
|
throw new Exception();
|
|
}
|
|
var end = st.LastIndexOf(')');
|
|
if (end != st.Length - 1)
|
|
{
|
|
throw new Exception(ErrorStrNotValidFormat);
|
|
}
|
|
st = st.Remove(st.Length-1).Remove(0, 1).ToString();
|
|
var node = new SNodeFull(false);
|
|
Deserialize(ref st, node);
|
|
return node;
|
|
}
|
|
|
|
private void Deserialize(ref string st, SNodeFull root)
|
|
{
|
|
st = st.Trim();
|
|
if (string.IsNullOrEmpty(st))
|
|
{
|
|
return;
|
|
}
|
|
|
|
SNodeFull node = null;
|
|
SNodeFull r = root;
|
|
do
|
|
{
|
|
while (st[0] == ')')
|
|
{
|
|
st = st.Remove(0, 1).Trim();
|
|
if (st.Length==0)
|
|
{
|
|
return;
|
|
}
|
|
r = root.RootNode;
|
|
if (r==null)
|
|
{
|
|
throw new Exception(ErrorStrNotValidFormat);
|
|
}
|
|
}
|
|
node = DeserializeItem(ref st);
|
|
st = st.Trim();
|
|
|
|
r.AddNode(node);
|
|
|
|
if (!node.IsLeaf)
|
|
{
|
|
Deserialize(ref st,node);
|
|
}
|
|
}
|
|
while (st.Length > 0);
|
|
|
|
}
|
|
|
|
private SNodeFull DeserializeItem(ref string st)
|
|
{
|
|
if (st[0] == '(')
|
|
{
|
|
st = st.Remove(0, 1);
|
|
return new SNodeFull(false);
|
|
}
|
|
|
|
var x = 0;
|
|
var esc = 0;
|
|
for (int i = 0; i < st.Length; i++)
|
|
{
|
|
if (st[i] == '"')
|
|
{
|
|
if (esc == 0)
|
|
{
|
|
esc = 1;
|
|
}
|
|
else if(esc == 1 && (i> 0 && st[i - 1] == '\\'))
|
|
{
|
|
throw new Exception(ErrorStrNotValidFormat);
|
|
}
|
|
else
|
|
{
|
|
esc = 2;
|
|
break;
|
|
}
|
|
}
|
|
else if (esc==0 && " ()".Contains(st[i]))
|
|
{
|
|
break;
|
|
}
|
|
|
|
x++;
|
|
}
|
|
if (esc == 1)
|
|
{
|
|
throw new Exception(ErrorStrNotValidFormat);
|
|
}
|
|
|
|
var head = esc==0? st.Substring(0, x): st.Substring(1,x-1);
|
|
st = st.Remove(0, esc ==0 ? x: x + 2);
|
|
return new SNodeFull(head, true);
|
|
}
|
|
}
|
|
}
|