using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace Cryville.Common.Pdt { #if false [Obsolete] public static class PdtReader { readonly static char[] ws = { ' ', '\t', '\n', '\r' }; readonly static char[] spunc = { ' ', '\t', '\n', '\r', '{', '}', ';' }; readonly static char[] ipunc = { ' ', '\t', '\n', '\r', '{', '}', ';', ':' }; readonly static char[] vpunc = { '{', '}', ';' }; static int pos; static string data; static char cc { get { return data[pos]; } } static bool eof { get { return pos == data.Length; } } static Dictionary definitions; public static T Read(string _data, Binder binder = null) { data = _data; pos = 0; definitions = new Dictionary(); while (true) { if (cc == '#') { SkipChar(); var s = GetIdentifier(); switch (s) { case "ver": var s2 = GetString(); if (s2 != "1") throw new FormatException("Invalid PDT version"); continue; case "define": var s3 = GetString(); var s4 = GetValue(); definitions.Add(s3, new Expression(s4, definitions)); SkipChar(); // TODO continue; default: SkipLine(); continue; } } break; } if (binder == null) binder = BinderAttribute.CreateBinderOfType(typeof(T)); return (T)ParseObject(typeof(T), binder); } static object ParseObject(Type type, Binder binder) { // TODO Binder object obj = type.GetConstructor(new Type[]{}).Invoke(new object[]{}); while (true) { if (eof) return obj; string str = GetValue(); if (cc == '{') { // List item SkipChar(); string strkey = str; if (typeof(IDictionary).IsAssignableFrom(type)) { var ktype = type.GetGenericArguments()[0]; var ptype = type.GetGenericArguments()[1]; object key = binder.ChangeType(strkey, ktype, null); object value = ParseObject(ptype, binder); ((IDictionary)obj).Add(key, value); } else { MemberInfo prop = null; Type ttype = null; bool flag = ReflectionHelper.TryFindMemberWithAttribute(type, out prop); if (!flag) prop = ReflectionHelper.GetMember(type, strkey); ttype = ReflectionHelper.GetMemberType(prop); if (!typeof(IDictionary).IsAssignableFrom(ttype)) { throw new NotImplementedException(); } else { var ktype = ttype.GetGenericArguments()[0]; var ptype = ttype.GetGenericArguments()[1]; if (flag) { object key = binder.ChangeType(strkey, ktype, null); object value = ParseObject(ptype, binder); ((IDictionary)ReflectionHelper.GetValue(prop, obj)).Add(key, value); } else { ReflectionHelper.SetValue(prop, obj, ParseObject(ttype, binder)); } } } } else if (cc == ';') { // Single property SkipChar(); string strkey; MemberInfo prop = null; if (str[0] == '*') { // Component-like property strkey = str.Substring(1); prop = ReflectionHelper.FindMemberWithAttribute(type); var ttype = ReflectionHelper.GetMemberType(prop); if (!typeof(IList).IsAssignableFrom(ttype)) throw new Exception(); // TODO var ktype = ttype.GetGenericArguments()[0]; object key = binder.ChangeType(strkey, ktype, null); ((IList)ReflectionHelper.GetValue(prop, obj)).Add(key); } else { // Common property var kv = str.Split(new char[]{':'}, 2); strkey = kv[0]; // TODO if (typeof(IDictionary).IsAssignableFrom(type)) { var ktype = type.GetGenericArguments()[0]; var ptype = type.GetGenericArguments()[1]; object key = binder.ChangeType(strkey, ktype, null); object value = binder.ChangeType(new Expression( kv.Length == 1 ? "true" : kv[1], definitions ), ptype, null); ((IDictionary)obj).Add(key, value); } else { bool flag = ReflectionHelper.TryFindMemberWithAttribute(type, out prop); if (!flag) prop = ReflectionHelper.GetMember(type, strkey); var ttype = ReflectionHelper.GetMemberType(prop); if (!typeof(IDictionary).IsAssignableFrom(ttype)) { object value = binder.ChangeType(new Expression( kv.Length == 1 ? "true" : kv[1], definitions ), ttype, null); ReflectionHelper.SetValue(prop, obj, value, binder); } else { var ktype = ttype.GetGenericArguments()[0]; var ptype = ttype.GetGenericArguments()[1]; object key = binder.ChangeType(strkey, ktype, null); object value = binder.ChangeType(new Expression( kv.Length == 1 ? "true" : kv[1], definitions ), ptype, null); ((IDictionary)ReflectionHelper.GetValue(prop, obj)).Add(key, value); } } } } else if (cc == '}') { try { SkipChar(); } catch (IndexOutOfRangeException) { } return obj; } else throw new Exception(); // TODO } } static void SkipChar() { pos++; SkipWs(); } static void SkipWs() { while (true) { for (; ws.Contains(cc); pos++); if (data[pos] == '/' && data[pos + 1] == '*') { for (; data[pos] != '*' || data[pos+1] != '/'; pos++); pos += 2; } else return; } } static string GetIdentifier() { SkipWs(); string r = ""; for (; !ipunc.Contains(cc); pos++) r += cc; SkipWs(); return r; } static string GetString() { SkipWs(); string r = ""; for (; !spunc.Contains(cc); pos++) r += cc; SkipWs(); return r; } static string GetValue() { SkipWs(); string r = ""; for (; !vpunc.Contains(cc); pos++) r += cc; SkipWs(); return r.Trim(); } static void SkipLine() { for (; cc != '\n'; pos++); SkipWs(); } } #endif public class ElementListAttribute : Attribute { } public class ComponentListAttribute : Attribute { } public class PropertyListAttribute : Attribute { } #if false [Obsolete] public abstract class ExpBase { public string exp { get; private set; } public ExpBase(string s) { exp = s; } public override string ToString() { return exp; } } [Obsolete] public abstract class ValueBase : ExpBase { public ValueBase(string s) : base(s) { } object preEvalResult; byte preEvalDepth = 0; public bool IsDynamic { get { return preEvalDepth == 0; } } protected abstract object EvalInternal(IEvaluator etor); public void PreEval(IEvaluator etor, byte depth = 1) { if (depth == 0) throw new ArgumentException("depth cannot be 0"); if (preEvalDepth != 0 && preEvalDepth < depth) return; try { preEvalResult = PreEvalInternal(etor, depth); preEvalDepth = depth; } catch (Exception) { } } protected virtual object PreEvalInternal(IEvaluator etor, byte depth) { return Eval(etor); } public object Eval(IEvaluator etor) { if (preEvalDepth != 0) return preEvalResult; return EvalInternal(etor); } } [Obsolete] public class Identifier : ValueBase { public Identifier(string s) : base(s) { } protected override object EvalInternal(IEvaluator etor) { return etor.EvalIdentifier(exp); } } [Obsolete] public class Operand : ExpBase { public OperandPriority Priority { get; private set; } public Operand(string s) : base(s) { switch (s) { case ".": Priority = OperandPriority.Prop; break; case "*": case "/": Priority = OperandPriority.Mul; break; case "+": case "-": Priority = OperandPriority.Add; break; case " ": case ",": Priority = OperandPriority.Sep; break; default: Priority = OperandPriority.None; break; } } public Operand(string s, OperandPriority p) : base(s) { Priority = p; } } [Obsolete] public enum OperandPriority { None = 0, Prop = 5, NeibMul = 4, Mul = 3, Add = 2, Sep = 1 } [Obsolete] public abstract class ConstantBase : ValueBase { public ConstantBase(string s) : base(s) { } } [Obsolete] public class CNumber : ConstantBase { public CNumber(string s) : base(s) { } protected override object EvalInternal(IEvaluator etor) { return etor.ParseNumber(exp); } } [Obsolete] public class CString : ConstantBase { public CString(string s) : base(s) { } protected override object EvalInternal(IEvaluator etor) { return etor.ParseString(exp); } } [Obsolete] public class BracketInitial : ExpBase { public BracketInitial() : base("(") { } } [Obsolete] public class BracketFinal : ExpBase { public BracketFinal() : base(")") { } } [Obsolete] public class Expression : ValueBase { List estack = new List(); List ostack = new List(); StackType type; enum StackType { Root, Unary, Bracketed, Supportive, Function } readonly OperandPriority Priority; public Expression(string s, Dictionary def) : base("") { var exp = s.Trim(); type = StackType.Root; int pos = 0; var b = new List(); while (pos < exp.Length) { b.Add(Forward(ref exp, ref pos)); } var lb = b[b.Count - 1]; if (def.ContainsKey(lb.exp)) { b.Add(def[lb.exp]); b.Remove(lb); } for (int i = b.Count - 2; i >= 0; i--) { // TODO Insertion var lhb = b[i]; var rhb = b[i + 1]; if (lhb is ConstantBase || lhb is Expression || lhb is BracketFinal) { if (rhb is Identifier || rhb is Expression || rhb is BracketInitial) { b.Insert(i + 1, new Operand("*", OperandPriority.NeibMul)); } } else if (lhb is Identifier) { if (rhb is Expression) { b.Insert(i + 1, new Operand("*", OperandPriority.NeibMul)); } if (def.ContainsKey(lhb.exp)) { b.Insert(i, def[lhb.exp]); b.Remove(lhb); } } } int p = 0; estack.Add(new Expression(b, ref p, StackType.Bracketed, def)); } public Expression Clone() { var r = (Expression)this.MemberwiseClone(); var es = new ValueBase[estack.Count]; estack.CopyTo(es); r.estack = es.ToList(); var os = new Operand[ostack.Count]; ostack.CopyTo(os); r.ostack = os.ToList(); return r; } Expression(List b, ref int p, StackType t, Dictionary def) : base("") { type = t; if (t == StackType.Unary) { ostack.Add((Operand)b[p]); p++; } while (p < b.Count - 1) { if (estack.Count == 0) { var b0 = b[p]; if (b0 is Operand) { var lp = p; var e = new Expression( b, ref p, StackType.Unary, def ); b.Insert(p, e); b.RemoveRange(lp, p - lp); p = lp; } else if (b0 is BracketInitial) { var lp = p; p++; var e = new Expression( b, ref p, StackType.Bracketed, def ); b.Insert(p, e); b.RemoveRange(lp, p - lp); p = lp; } estack.Add((ValueBase)b[p]); p++; if (t == StackType.Unary) { if (estack.Count != 1) throw new Exception(); // TODO else return; } } if (p >= b.Count) return; var b1 = b[p]; if (b1 is BracketFinal) { if (t == StackType.Bracketed) p++; return; } var b2 = b[p + 1]; if (b2 is BracketInitial) { var lp = p + 1; p += 2; var e = new Expression( b, ref p, StackType.Bracketed, def ); b.Insert(p, e); b.RemoveRange(lp, p - lp); p = lp - 1; b2 = b[p + 1]; } if (b1 is Operand) { if (estack.Count == 1) Priority = ((Operand)b1).Priority; if (b2 is Operand) { var lp = p + 1; p++; var e = new Expression( b, ref p, StackType.Unary, def ); b.Insert(p, e); b.RemoveRange(lp, p - lp); p = lp - 1; b2 = b[p + 1]; } if (p + 2 >= b.Count) { ostack.Add((Operand)b1); estack.Add((ValueBase)b2); p += 2; return; } var b3 = b[p + 2]; if (b3 is BracketFinal) { ostack.Add((Operand)b1); estack.Add((ValueBase)b2); p += 2; if (t == StackType.Bracketed) p++; return; } else if (b3 is Operand) { var o1 = (Operand)b1; var o2 = (Operand)b3; if (o2.Priority == Priority) { ostack.Add(o1); estack.Add((ValueBase)b2); p += 2; continue; } else if (o2.Priority > Priority) { var lp = p + 1; p++; var e = new Expression( b, ref p, StackType.Supportive, def ); b.Insert(p, e); b.RemoveRange(lp, p - lp); p = lp - 1; continue; } else if (o2.Priority < Priority) { ostack.Add(o1); estack.Add((ValueBase)b2); // b.RemoveRange(0, 2); if (type == StackType.Bracketed) { Expression cl = this.Clone(); cl.type = StackType.Supportive; estack.Clear(); ostack.Clear(); estack.Add(cl); Priority = o2.Priority; p += 2; continue; } else { type = StackType.Supportive; p += 2; return; } } } else throw new Exception(); // TODO } else throw new Exception(); // TODO throw new Exception(); // TODO /*if (lb is Identifier) { if (def.ContainsKey(lb.exp)) { b.Add(def[lb.exp]); b.Remove(lb); } } // Unary if (estack.Count == 0) { if (b[0] is Operand) { b.Add(new Expression( b, ref p, StackType.Unary, def )); b.RemoveAt(0); } if (b[0] is ValueBase) { estack.Add((ValueBase)b[0]); b.RemoveAt(0); if (type == StackType.Unary) return; if (b.Count == 0) continue; } } if (estack.Count == 1) { if (b[0] is Operand) Priority = ((Operand)b[0]).Priority; } // Bracket if (lb is BracketInitial) { b.Remove(lb); b.Add(new Expression(b, ref p, StackType.Bracketed, def)); } else if (lb is BracketFinal) { if (type != StackType.Bracketed) p--; foreach (var i in b) { if (i is Operand) ostack.Add((Operand)i); else if (i is BracketFinal) return; else estack.Add((ValueBase)i); } } var c = b.Count; if (c <= 1) continue; // Two blocks lb = b[c - 1]; var lb1 = b[c - 2]; if (lb is Operand && lb1 is Operand) { b.Add(new Expression( b, ref p, StackType.Unary, def )); b.RemoveAt(b.Count - 2); } c = b.Count; if (c <= 2) continue; // Three blocks var b0 = b[0]; var b1 = b[1]; var b2 = b[2]; if (!(b0 is Operand)) throw new Exception(); // TODO if (!(b1 is ValueBase)) throw new Exception(); // TODO if (!(b2 is Operand)) throw new Exception(); // TODO var o1 = (Operand)b0; var o2 = (Operand)b2; if (o2.Priority == Priority) { ostack.Add(o1); estack.Add((ValueBase)b1); b.Remove(o1); b.Remove(b1); continue; } if (o2.Priority > Priority) { b.Add(new Expression( b, ref p, StackType.Supportive, def )); b.RemoveRange(1, b.Count - 2); continue; } if (o2.Priority < Priority) { ostack.Add(o1); estack.Add((ValueBase)b1); b.RemoveRange(0, 2); if (type == StackType.Bracketed) { Expression cl = this.Clone(); cl.type = StackType.Supportive; estack.Clear(); ostack.Clear(); estack.Add(cl); Priority = o2.Priority; } else { type = StackType.Supportive; // p = o2.Index; return; } }*/ } estack.Add((ValueBase)b[b.Count - 1]); p++; } ExpBase Forward(ref string s, ref int p) { char sc = s[p]; string r = ""; if (cat(sc) == 3) { p++; return new BracketInitial(); } else if (cat(sc) == 4) { p++; return new BracketFinal(); } else if (cat(sc) == 5) { for (; p < s.Length; p++) { if (cat(s[p]) != 5) break; r += s[p]; } if (r == ".") return new Operand(r); else return new CNumber(r); } else if (cat(sc) == 2) { p++; for (; s[p] != sc; p++) r += s[p]; p++; return new CString(r); } else if (cat(sc) == 0) { for (; p < s.Length; p++) { if (cat(s[p]) != 0) break; r += s[p]; } if (p == s.Length) return new Identifier(r); if (s[p] == '(') return new Operand(r); else return new Identifier(r); } else if (cat(sc) == 1) { p++; return new Operand(sc.ToString()); } else throw new Exception(); // TODO } protected override object EvalInternal(IEvaluator etor) { if (type == StackType.Unary) { if (ostack[0].Priority == OperandPriority.None) return etor.OperateFunction(ostack[0], estack[0].Eval(etor)); else return etor.OperateUnary(ostack[0], estack[0].Eval(etor)); } else { object r = estack[0].Eval(etor); for (int i = 0; i < ostack.Count; i++) { r = etor.OperateBinary( ostack[i], r, estack[i+1].Eval(etor) ); } return r; } } public T Eval(IEvaluator etor) { return (T)etor.Cast(typeof(T), EvalInternal(etor)); } protected override object PreEvalInternal(IEvaluator etor, byte depth) { try { return EvalInternal(etor); } catch (Exception) { foreach (var v in estack) v.PreEval(etor, depth); throw; } } // 0: Other, 1: Operand, 2: String, // 3: SOE, 4: EOE, 5: Number static readonly byte[] ctl = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 1, 0, 1, 1, 2, 3, 4, 1, 1, 1, 1, 5, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, }; static byte cat(char c) { if (c >> 7 != 0) return 0; else return ctl[c]; } public override string ToString() { if (type == StackType.Unary) return string.Format("{0}{1}", ostack[0], estack[0]); if (type == StackType.Function) return string.Format("{0}{1}", ostack[0], estack[0]); string r = estack[0].ToString(); for (int i = 0; i < ostack.Count; i++) { r += ostack[i].ToString(); r += estack[i + 1].ToString(); } if (type == StackType.Bracketed) r = string.Format("({0})", r); return r; } } [Obsolete] public interface IEvaluator { object ParseNumber(string exp); object ParseString(string exp); object EvalIdentifier(string exp); object OperateUnary(Operand op, object q); object OperateBinary(Operand op, object q, object r); object OperateFunction(Operand op, object q); // TODO [Obsolete] object Cast(Type type, object obj); //public abstract Func GetCastCallback(Type dest, Type source); } #endif }