using Cryville.Common; using Cryville.Common.Pdt; using Cryville.Crtr.Components; using System; using System.Collections.Generic; using System.Reflection; namespace Cryville.Crtr { public class SkinInterpreter : PdtInterpreter { public SkinInterpreter(string src, Binder binder) : base(src, typeof(PdtSkin), binder) { } readonly List s = new List(); readonly HashSet a = new HashSet(); readonly List k = new List(2); protected override object InterpretKey(Type type) { 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"); if (a.Contains("has")) { if (k.Count != 1) throw new FormatException("Invalid anchor name"); return new SkinPropertyKey.CreateAnchor { Name = IdentifierManager.SharedInstance.Request(k[0]) }; } else if (a.Contains("at")) { if (k.Count != 1) throw new FormatException("Invalid anchor name"); return new SkinPropertyKey.SetAnchor { Name = IdentifierManager.SharedInstance.Request(k[0]) }; } switch (k.Count) { case 1: if (compKeyFlag) return new SkinPropertyKey.CreateComponent { Component = GetComponentByName(k[0]) }; else return new SkinPropertyKey.SetProperty { Component = typeof(TransformInterface), Name = IdentifierManager.SharedInstance.Request(k[0]) }; case 2: return new SkinPropertyKey.SetProperty { Component = GetComponentByName(k[0]), Name = IdentifierManager.SharedInstance.Request(k[1]) }; default: throw new FormatException("Unknown error"); // Unreachable } case '{': return new SkinSelectors(s, a); case '}': return null; 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"); } } static Type GetComponentByName(string name) { Type result; if (GenericResources.Components.TryGetValue(name, out result)) return result; throw new ArgumentException(string.Format("Component type \"{0}\" not found", name)); } } }