Files
crtr/Assets/Cryville/Common/Pdt/PdtReader.cs
2022-09-30 17:32:21 +08:00

750 lines
19 KiB
C#

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<string, Expression> definitions;
public static T Read<T>(string _data, Binder binder = null) {
data = _data;
pos = 0;
definitions = new Dictionary<string, Expression>();
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<ElementListAttribute>(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<ComponentListAttribute>(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<PropertyListAttribute>(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<ValueBase> estack = new List<ValueBase>();
List<Operand> ostack = new List<Operand>();
StackType type;
enum StackType {
Root, Unary, Bracketed, Supportive, Function
}
readonly OperandPriority Priority;
public Expression(string s, Dictionary<string, Expression> def) : base("") {
var exp = s.Trim();
type = StackType.Root;
int pos = 0;
var b = new List<ExpBase>();
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<ExpBase> b, ref int p, StackType t, Dictionary<string, Expression> 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<T>(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<Type, object, object> GetCastCallback(Type dest, Type source);
}
#endif
}