using System.Collections; using System.Reflection; using System.Text; using Antlr4.Runtime; using Newtonsoft.Json; namespace meowlang.parser; [AttributeUsage(AttributeTargets.Property)] public class IgnoreAttribute : Attribute { } public static class ObjectExtensions { public static string AutoToString(this object? o, bool prettyPrint = true, bool encapsulate = true) { if (o == null) return "null"; var type = o.GetType(); if (o is string s) { var escaped = s.Replace("\\", "\\\\").Replace("\"", "\\\""); return $"\"{escaped}\""; } if (o is bool b) { return b ? "true" : "false"; } if (type.IsPrimitive) { return o.ToString()!; } if (type.IsEnum) { var val = Enum.GetName(type, o); return $"\"{val}\""; } string json; if (type.IsAssignableTo(typeof(IEnumerable))) { var enumerable = (o as IEnumerable)!.Cast(); var sb = new StringBuilder(); sb.Append('['); sb.AppendJoin(", ", enumerable.Select(x => x.AutoToString(false))); sb.Append(']'); json = sb.ToString(); } else { var properties = type.GetProperties(); var sb = new StringBuilder(); sb.Append('{'); sb.Append($"\"@type\": \"{type.Name}\""); for (var index = 0; index < properties.Length; index++) { var propertyInfo = properties[index]; if (propertyInfo.GetCustomAttribute() != null) continue; sb.Append(','); sb.Append($"\"{propertyInfo.Name}\": "); var propertyValue = propertyInfo.GetValue(o); sb.Append(propertyValue.AutoToString()); } sb.Append('}'); json = sb.ToString(); } if (prettyPrint) { var temp = JsonConvert.DeserializeObject(json); json = JsonConvert.SerializeObject(temp, Formatting.Indented); } return json; } } internal static class ParserRuleContextExtensions { public static Span GetSpan(this ParserRuleContext context) { return new Span(context.Start.TokenSource.SourceName, context.Start.StartIndex, context.Stop.StopIndex); } } internal static class TokenExtensions { public static Span GetSpan(this IToken token) { return new Span(token.TokenSource.SourceName, token.StartIndex, token.StopIndex); } } internal static class StringExtensions { public static string Unescape(this string str) { StringBuilder builder = new(); var startPos = 0; int backslashPos; while ((backslashPos = str.IndexOf('\\', startPos)) > -1) { builder.Append(str[startPos..backslashPos]); int length; string ch; switch (str[backslashPos + 1]) { case '\\': ch = "\\"; length = 1; break; case '\'': ch = "'"; length = 1; break; case '"': ch = "\""; length = 1; break; default: throw new InvalidEscapeSequenceException($"\\{str[backslashPos + 1]}"); } builder.Append(ch); startPos = backslashPos + length + 1; } builder.Append(str[startPos..]); return builder.ToString(); } }