Skip to content

Instantly share code, notes, and snippets.

@deiuch
Last active June 1, 2019 13:54
Show Gist options
  • Save deiuch/283258b74b1cf40b96a44995ccc3822d to your computer and use it in GitHub Desktop.
Save deiuch/283258b74b1cf40b96a44995ccc3822d to your computer and use it in GitHub Desktop.
Code from SLang project on parser's AST serialization into JSON IR
using System;
using System.Collections.Generic;
using System.Linq;
namespace SLang.Service
{
public class JsonIr
{
public const string JSON_NULL_REPRESENTATION = "null";
public static string NL { get; set; } = Environment.NewLine;
public static string INDENT { get; set; } = " ";
private string type;
private string value;
private List<JsonIr> children = new List<JsonIr>();
public JsonIr(Type type) : this(type, null) { }
public JsonIr(Type type, string value) : this(type.Name, value) { }
public JsonIr(string typeName) : this(typeName, null) { }
public JsonIr(string typeName, string value)
{
this.type = typeName ?? throw new ArgumentNullException();
this.value = value;
}
public JsonIr SetValue(string value)
{
this.value = value;
return this;
}
public JsonIr AppendChild(JsonIr child)
{
children.Add(child ?? GetIrNull());
return this;
}
public virtual string Serialize(bool indentation)
{
return String.Format(
"{{{0}" +
"{1}\"type\":{2},{0}" +
"{1}\"value\":{3},{0}" +
// "{1}\"num_children\":" + children.Count() + ",{0}" +
"{1}\"children\":[" +
(children.Count() > 0 ? "{0}{1}{1}{4}{0}{1}" : "") +
"]{0}" +
"}}",
indentation ? NL : "", // 0, newline
indentation ? INDENT : "", // 1, tabulation
JsonifyString(type), // 2, type string
JsonifyString(value), // 3, value string
string.Join( // 4, childern array
"," + (indentation ? NL + INDENT + INDENT : ""),
children.Select( // indent each line twice
o => o.Serialize(indentation).
Replace(NL, NL + INDENT + INDENT)
)
)
);
}
private static string JsonifyString(string s)
{
if (s == null)
return JSON_NULL_REPRESENTATION;
//return System.Web.Helpers.Json.Encode(s);
return "\"" + string.Concat(s.Select(
c => char.IsControl(c) ?
string.Format("\\u{0:X4}", (ushort)c) :
c == '"' ?
"\\\"" :
c == '\\' ?
"\\\\" :
c.ToString()
)) + "\"";
}
public static JsonIr ListToJSON<T>(List<T> entities_list) where T : ENTITY
{
if (entities_list == null)
throw new ArgumentNullException();
JsonIr irList = new JsonIr(typeof(T).Name + "_LIST");
foreach (ENTITY e in entities_list)
irList.AppendChild(e.ToJSON());
return irList;
}
public static JsonIr GetIrNull()
{
return JsonIrNull.Get();
}
private class JsonIrNull : JsonIr
{
private static JsonIrNull instance;
private JsonIrNull() : base(JSON_NULL_REPRESENTATION) { }
public static JsonIrNull Get()
{
if (instance == null)
instance = new JsonIrNull();
return instance;
}
public override string Serialize(bool indentation)
{
return JSON_NULL_REPRESENTATION;
}
}
#region Example
public class Token
{
public string image { get; private set; } // = "+";
// ...other members, constructors and useful methods...
}
public abstract class ENTITY
{
// ...members, constructors and other useful methods...
public virtual JsonIr ToJSON()
{
return new JsonIr(GetType());
}
public static JsonIr ToJSON(ENTITY e)
{
if (e == null) return JsonIr.GetIrNull();
return e.ToJSON();
}
}
public abstract class TYPE : ENTITY
{
// ...members, constructors and other useful methods...
}
public abstract class EXPRESSION : ENTITY
{
public TYPE type { get; protected set; }
// ...constructors and other useful methods...
public override JsonIr ToJSON()
{
return base.ToJSON()
.AppendChild(ToJSON(type));
}
}
public class UNARY : EXPRESSION
{
public EXPRESSION primary { get; private set; }
public Token unaryOp; // = new Token();
// ...constructors and other useful methods...
public override JsonIr ToJSON()
{
return base.ToJSON()
.SetValue(unaryOp.image)
.AppendChild(ToJSON(primary));
}
}
static void Main(string[] args)
{
JsonIr example_object = new UNARY(/* args */).ToJSON();
string result = example_object.Serialize(true);
Console.WriteLine(result);
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment