750 lines
19 KiB
C#
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
|
|
}
|