using Cryville.Common.Pdt; using System; using System.Collections.Generic; using System.Reflection; namespace Cryville.Crtr.Skin { public class SkinInterpreter : PdtInterpreter { public SkinInterpreter(string src, Binder binder) : base(src, binder) { } readonly List s = new(); readonly HashSet a = new(); readonly List k = new(2); protected override object InterpretKey(Type type) { if (typeof(SkinElement).IsAssignableFrom(type)) return InterpretSkinElementKey(); else if (typeof(AnimationSpan).IsAssignableFrom(type)) return InterpretAnimationSpanKey(); else return base.InterpretKey(type); } object InterpretSkinElementKey() { s.Clear(); a.Clear(); k.Clear(); bool invalidKeyFlag = false, compKeyFlag = false; while (true) { int pp = Position; switch (cc) { case '@': GetChar(); a.Add(GetIdentifier()); break; case '$': GetChar(); s.Add(new SkinSelector.CreateObject()); invalidKeyFlag = true; break; case '.': GetChar(); if (cc == '.') { GetChar(); s.Add(new SkinSelector.AtAnchor(GetIdentifier())); invalidKeyFlag = true; } else { var p3 = GetIdentifier(); s.Add(new SkinSelector.Anchor(p3)); if (!invalidKeyFlag) { if (k.Count != 1) invalidKeyFlag = true; else k.Add(p3); } } break; case '>': GetChar(); s.Add(new SkinSelector.Property(GetExp())); break; case ';': case ':': if (invalidKeyFlag) throw new FormatException("Invalid key format"); return SkinPropertyKey.Construct(a, k, compKeyFlag); case '{': return new SkinSelectors(s, a); case '}': throw new FormatException("Invalid token"); case '*': GetChar(); compKeyFlag = true; break; default: var p4 = GetIdentifier(); s.Add(new SkinSelector.ElementType(p4)); if (!invalidKeyFlag) { if (k.Count != 0) invalidKeyFlag = true; else k.Add(p4); } break; } ws(); if (Position == pp) throw new FormatException("Invalid selector or key format"); } } object InterpretAnimationSpanKey() { if ((ct & CharCategory.Digit) != 0 || cc == ',') { float start = 0, end = 1; if (cc != ',') { start = float.Parse(GetNumber()); ws(); if (cc != ',') throw new FormatException("Invalid span format"); } GetChar(); ws(); if (cc != '{') end = float.Parse(GetNumber()); ws(); if (cc != '{') throw new FormatException("Invalid span format"); return new Clip(start, end); } a.Clear(); k.Clear(); while (true) { int pp = Position; switch (cc) { case '.': GetChar(); if (k.Count != 1) throw new FormatException("Invalid key format"); k.Add(GetIdentifier()); break; case ';': case ':': return SkinPropertyKey.Construct(a, k, false); case '{': throw new FormatException("Invalid token"); case '}': throw new FormatException("Invalid token"); default: if (k.Count != 0) throw new FormatException("Invalid key format"); k.Add(GetIdentifier()); break; } ws(); if (Position == pp) throw new FormatException("Invalid selector or key format"); } } } }