using System; using System.Collections.Generic; using System.Text; using NTERA.EmuEra.Game.EraEmu.GameData.Function; using NTERA.EmuEra.Game.EraEmu.GameData.Variable; using NTERA.EmuEra.Game.EraEmu.Sub; namespace NTERA.EmuEra.Game.EraEmu.GameData.Expression { /// /// 引数のチェック、戻り値の型チェック等は全て呼び出し元が責任を負うこと。 /// internal abstract class OperatorMethod : FunctionMethod { public OperatorMethod() { argumentTypeArray = null; } public override string CheckArgumentType(string name, IOperandTerm[] arguments) { throw new ExeEE("型チェックは呼び出し元が行うこと"); } } internal static class OperatorMethodManager { static readonly Dictionary unaryDic = new Dictionary(); static readonly Dictionary unaryAfterDic = new Dictionary(); static readonly Dictionary binaryIntIntDic = new Dictionary(); static readonly Dictionary binaryStrStrDic = new Dictionary(); static readonly OperatorMethod binaryMultIntStr; static readonly OperatorMethod ternaryIntIntInt; static readonly OperatorMethod ternaryIntStrStr; static OperatorMethodManager() { unaryDic[OperatorCode.Plus] = new PlusInt(); unaryDic[OperatorCode.Minus] = new MinusInt(); unaryDic[OperatorCode.Not] = new NotInt(); unaryDic[OperatorCode.BitNot] = new BitNotInt(); unaryDic[OperatorCode.Increment] = new IncrementInt(); unaryDic[OperatorCode.Decrement] = new DecrementInt(); unaryAfterDic[OperatorCode.Increment] = new IncrementAfterInt(); unaryAfterDic[OperatorCode.Decrement] = new DecrementAfterInt(); binaryIntIntDic[OperatorCode.Plus] = new PlusIntInt(); binaryIntIntDic[OperatorCode.Minus] = new MinusIntInt(); binaryIntIntDic[OperatorCode.Mult] = new MultIntInt(); binaryIntIntDic[OperatorCode.Div] = new DivIntInt(); binaryIntIntDic[OperatorCode.Mod] = new ModIntInt(); binaryIntIntDic[OperatorCode.Equal] = new EqualIntInt(); binaryIntIntDic[OperatorCode.Greater] = new GreaterIntInt(); binaryIntIntDic[OperatorCode.Less] = new LessIntInt(); binaryIntIntDic[OperatorCode.GreaterEqual] = new GreaterEqualIntInt(); binaryIntIntDic[OperatorCode.LessEqual] = new LessEqualIntInt(); binaryIntIntDic[OperatorCode.NotEqual] = new NotEqualIntInt(); binaryIntIntDic[OperatorCode.And] = new AndIntInt(); binaryIntIntDic[OperatorCode.Or] = new OrIntInt(); binaryIntIntDic[OperatorCode.Xor] = new XorIntInt(); binaryIntIntDic[OperatorCode.Nand] = new NandIntInt(); binaryIntIntDic[OperatorCode.Nor] = new NorIntInt(); binaryIntIntDic[OperatorCode.BitAnd] = new BitAndIntInt(); binaryIntIntDic[OperatorCode.BitOr] = new BitOrIntInt(); binaryIntIntDic[OperatorCode.BitXor] = new BitXorIntInt(); binaryIntIntDic[OperatorCode.RightShift] = new RightShiftIntInt(); binaryIntIntDic[OperatorCode.LeftShift] = new LeftShiftIntInt(); binaryStrStrDic[OperatorCode.Plus] = new PlusStrStr(); binaryStrStrDic[OperatorCode.Equal] = new EqualStrStr(); binaryStrStrDic[OperatorCode.Greater] = new GreaterStrStr(); binaryStrStrDic[OperatorCode.Less] = new LessStrStr(); binaryStrStrDic[OperatorCode.GreaterEqual] = new GreaterEqualStrStr(); binaryStrStrDic[OperatorCode.LessEqual] = new LessEqualStrStr(); binaryStrStrDic[OperatorCode.NotEqual] = new NotEqualStrStr(); binaryMultIntStr = new MultStrInt(); ternaryIntIntInt = new TernaryIntIntInt(); ternaryIntStrStr = new TernaryIntStrStr(); } public static IOperandTerm ReduceUnaryTerm(OperatorCode op, IOperandTerm o1) { OperatorMethod method = null; if (op == OperatorCode.Increment || op == OperatorCode.Decrement) { VariableTerm var = o1 as VariableTerm; if (var == null) throw new CodeEE("変数以外をインクリメントすることはできません"); if (var.Identifier.IsConst) throw new CodeEE("変更できない変数をインクリメントすることはできません"); } if (o1.GetOperandType() == typeof(Int64)) { if (op == OperatorCode.Plus) return o1; if (unaryDic.ContainsKey(op)) method = unaryDic[op]; } if(method != null) return new FunctionMethodTerm(method, new[] { o1 }); string errMes = ""; if (o1.GetOperandType() == typeof(Int64)) errMes += "数値型"; else if (o1.GetOperandType() == typeof(string)) errMes += "文字列型"; else errMes += "不定型"; errMes += "に単項演算子\'" + OperatorManager.ToOperatorString(op) + "\'は適用できません"; throw new CodeEE(errMes); } public static IOperandTerm ReduceUnaryAfterTerm(OperatorCode op, IOperandTerm o1) { OperatorMethod method = null; if (op == OperatorCode.Increment || op == OperatorCode.Decrement) { VariableTerm var = o1 as VariableTerm; if (var == null) throw new CodeEE("変数以外をインクリメントすることはできません"); if (var.Identifier.IsConst) throw new CodeEE("変更できない変数をインクリメントすることはできません"); } if (o1.GetOperandType() == typeof(Int64)) { if (unaryAfterDic.ContainsKey(op)) method = unaryAfterDic[op]; } if (method != null) return new FunctionMethodTerm(method, new[] { o1 }); string errMes = ""; if (o1.GetOperandType() == typeof(Int64)) errMes += "数値型"; else if (o1.GetOperandType() == typeof(string)) errMes += "文字列型"; else errMes += "不定型"; errMes += "に後置単項演算子\'" + OperatorManager.ToOperatorString(op) + "\'は適用できません"; throw new CodeEE(errMes); } public static IOperandTerm ReduceBinaryTerm(OperatorCode op, IOperandTerm left, IOperandTerm right) { OperatorMethod method = null; if ((left.GetOperandType() == typeof(Int64)) && (right.GetOperandType() == typeof(Int64))) { if (binaryIntIntDic.ContainsKey(op)) method = binaryIntIntDic[op]; } else if ((left.GetOperandType() == typeof(string)) && (right.GetOperandType() == typeof(string))) { if (binaryStrStrDic.ContainsKey(op)) method = binaryStrStrDic[op]; } else if (((left.GetOperandType() == typeof(Int64)) && (right.GetOperandType() == typeof(string))) || ((left.GetOperandType() == typeof(string)) && (right.GetOperandType() == typeof(Int64)))) { if (op == OperatorCode.Mult) method = binaryMultIntStr; } if (method != null) return new FunctionMethodTerm(method, new[] { left, right }); string errMes = ""; if (left.GetOperandType() == typeof(Int64)) errMes += "数値型と"; else if (left.GetOperandType() == typeof(string)) errMes += "文字列型と"; else errMes += "不定型と"; if (right.GetOperandType() == typeof(Int64)) errMes += "数値型の"; else if (right.GetOperandType() == typeof(string)) errMes += "文字列型の"; else errMes += "不定型の"; errMes += "演算に二項演算子\'" + OperatorManager.ToOperatorString(op) + "\'は適用できません"; throw new CodeEE(errMes); } public static IOperandTerm ReduceTernaryTerm(OperatorCode op, IOperandTerm o1, IOperandTerm o2, IOperandTerm o3) { OperatorMethod method = null; if ((o1.GetOperandType() == typeof(Int64)) && (o2.GetOperandType() == typeof(Int64)) && (o3.GetOperandType() == typeof(Int64))) method = ternaryIntIntInt; else if ((o1.GetOperandType() == typeof(Int64)) && (o2.GetOperandType() == typeof(string)) && (o3.GetOperandType() == typeof(string))) method = ternaryIntStrStr; if (method != null) return new FunctionMethodTerm(method, new[] { o1, o2, o3 }); throw new CodeEE("三項演算子の使用法が不正です"); } #region OperatorMethod SubClasses private sealed class PlusIntInt : OperatorMethod { public PlusIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { return arguments[0].GetIntValue(exm) + arguments[1].GetIntValue(exm); } } private sealed class PlusStrStr : OperatorMethod { public PlusStrStr() { CanRestructure = true; ReturnType = typeof(string); argumentTypeArray = new[] { typeof(string), typeof(string) }; } public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false) { return arguments[0].GetStrValue(exm, tryTranslate) + arguments[1].GetStrValue(exm, tryTranslate); // JVN: Would be a great idea to attempt to translate both sides instead of just one here } } private sealed class MinusIntInt : OperatorMethod { public MinusIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { return arguments[0].GetIntValue(exm) - arguments[1].GetIntValue(exm); } } private sealed class MultIntInt : OperatorMethod { public MultIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { return arguments[0].GetIntValue(exm) * arguments[1].GetIntValue(exm); } } private sealed class MultStrInt : OperatorMethod { public MultStrInt() { CanRestructure = true; ReturnType = typeof(string); } public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false) { Int64 value = 0; string str = null; if (arguments[0].GetOperandType() == typeof(Int64)) { value = arguments[0].GetIntValue(exm); str = arguments[1].GetStrValue(exm, tryTranslate); } else { str = arguments[0].GetStrValue(exm, tryTranslate); value = arguments[1].GetIntValue(exm); } if (value < 0) throw new CodeEE("文字列に負の値(" + value + ")を乗算しようとしました"); if (value >= 10000) throw new CodeEE("文字列に10000以上の値(" + value + ")を乗算しようとしました"); if ((str == "") || (value == 0)) return ""; StringBuilder builder = new StringBuilder(); builder.Capacity = str.Length * (int)value; for (int i = 0; i < value; i++) { builder.Append(str); } return builder.ToString(); } } private sealed class DivIntInt : OperatorMethod { public DivIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { Int64 right = arguments[1].GetIntValue(exm); if (right == 0) throw new CodeEE("0による除算が行なわれました"); return arguments[0].GetIntValue(exm) / right; } } private sealed class ModIntInt : OperatorMethod { public ModIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { Int64 right = arguments[1].GetIntValue(exm); if (right == 0) throw new CodeEE("0による除算が行なわれました"); return arguments[0].GetIntValue(exm) % right; } } private sealed class EqualIntInt : OperatorMethod { public EqualIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { if (arguments[0].GetIntValue(exm) == arguments[1].GetIntValue(exm)) return 1L; return 0L; } } private sealed class EqualStrStr : OperatorMethod { public EqualStrStr() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { if (arguments[0].GetStrValue(exm) == arguments[1].GetStrValue(exm)) return 1L; return 0L; } } private sealed class NotEqualIntInt : OperatorMethod { public NotEqualIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { if (arguments[0].GetIntValue(exm) != arguments[1].GetIntValue(exm)) return 1L; return 0L; } } private sealed class NotEqualStrStr : OperatorMethod { public NotEqualStrStr() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { if (arguments[0].GetStrValue(exm) != arguments[1].GetStrValue(exm)) return 1L; return 0L; } } private sealed class GreaterIntInt : OperatorMethod { public GreaterIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { if (arguments[0].GetIntValue(exm) > arguments[1].GetIntValue(exm)) return 1L; return 0L; } } private sealed class GreaterStrStr : OperatorMethod { public GreaterStrStr() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { int c = string.Compare(arguments[0].GetStrValue(exm), arguments[1].GetStrValue(exm), Config.Config.SCExpression); if (c > 0) return 1L; return 0L; } } private sealed class LessIntInt : OperatorMethod { public LessIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { if (arguments[0].GetIntValue(exm) < arguments[1].GetIntValue(exm)) return 1L; return 0L; } } private sealed class LessStrStr : OperatorMethod { public LessStrStr() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { int c = string.Compare(arguments[0].GetStrValue(exm), arguments[1].GetStrValue(exm), Config.Config.SCExpression); if (c < 0) return 1L; return 0L; } } private sealed class GreaterEqualIntInt : OperatorMethod { public GreaterEqualIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { if (arguments[0].GetIntValue(exm) >= arguments[1].GetIntValue(exm)) return 1L; return 0L; } } private sealed class GreaterEqualStrStr : OperatorMethod { public GreaterEqualStrStr() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { int c = string.Compare(arguments[0].GetStrValue(exm), arguments[1].GetStrValue(exm), Config.Config.SCExpression); if (c < 0) return 1L; return 0L; } } private sealed class LessEqualIntInt : OperatorMethod { public LessEqualIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { if (arguments[0].GetIntValue(exm) <= arguments[1].GetIntValue(exm)) return 1L; return 0L; } } private sealed class LessEqualStrStr : OperatorMethod { public LessEqualStrStr() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { int c = string.Compare(arguments[0].GetStrValue(exm), arguments[1].GetStrValue(exm), Config.Config.SCExpression); if (c < 0) return 1L; return 0L; } } private sealed class AndIntInt : OperatorMethod { public AndIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { if ((arguments[0].GetIntValue(exm) != 0) && (arguments[1].GetIntValue(exm) != 0)) return 1L; return 0L; } } private sealed class OrIntInt : OperatorMethod { public OrIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { if ((arguments[0].GetIntValue(exm) != 0) || (arguments[1].GetIntValue(exm) != 0)) return 1L; return 0L; } } private sealed class XorIntInt : OperatorMethod { public XorIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { Int64 i1 = arguments[0].GetIntValue(exm); Int64 i2 = arguments[1].GetIntValue(exm); if (((i1 == 0) && (i2 != 0)) || ((i1 != 0) && (i2 == 0))) return 1L; return 0L; } } private sealed class NandIntInt : OperatorMethod { public NandIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { if ((arguments[0].GetIntValue(exm) == 0) || (arguments[1].GetIntValue(exm) == 0)) return 1L; return 0L; } } private sealed class NorIntInt : OperatorMethod { public NorIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { if ((arguments[0].GetIntValue(exm) == 0) && (arguments[1].GetIntValue(exm) == 0)) return 1L; return 0L; } } private sealed class BitAndIntInt : OperatorMethod { public BitAndIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { return arguments[0].GetIntValue(exm) & arguments[1].GetIntValue(exm); } } private sealed class BitOrIntInt : OperatorMethod { public BitOrIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { return arguments[0].GetIntValue(exm) | arguments[1].GetIntValue(exm); } } private sealed class BitXorIntInt : OperatorMethod { public BitXorIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { return arguments[0].GetIntValue(exm) ^ arguments[1].GetIntValue(exm); } } private sealed class RightShiftIntInt : OperatorMethod { public RightShiftIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { return arguments[0].GetIntValue(exm) >> (Int32)(arguments[1].GetIntValue(exm)); } } private sealed class LeftShiftIntInt : OperatorMethod { public LeftShiftIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { return arguments[0].GetIntValue(exm) << (Int32)(arguments[1].GetIntValue(exm)); } } private sealed class PlusInt : OperatorMethod { public PlusInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { return arguments[0].GetIntValue(exm); } } private sealed class MinusInt : OperatorMethod { public MinusInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { return -arguments[0].GetIntValue(exm); } } private sealed class NotInt : OperatorMethod { public NotInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { if (arguments[0].GetIntValue(exm) == 0) return 1L; return 0L; } } private sealed class BitNotInt : OperatorMethod { public BitNotInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { return ~arguments[0].GetIntValue(exm); } } private sealed class IncrementInt : OperatorMethod { public IncrementInt() { CanRestructure = false; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { VariableTerm var = (VariableTerm)arguments[0]; return var.PlusValue(1L, exm); } } private sealed class DecrementInt : OperatorMethod { public DecrementInt() { CanRestructure = false; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { VariableTerm var = (VariableTerm)arguments[0]; return var.PlusValue(-1L, exm); } } private sealed class IncrementAfterInt : OperatorMethod { public IncrementAfterInt() { CanRestructure = false; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { VariableTerm var = (VariableTerm)arguments[0]; return var.PlusValue(1L, exm) - 1; } } private sealed class DecrementAfterInt : OperatorMethod { public DecrementAfterInt() { CanRestructure = false; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { VariableTerm var = (VariableTerm)arguments[0]; return var.PlusValue(-1L, exm) + 1; } } private sealed class TernaryIntIntInt : OperatorMethod { public TernaryIntIntInt() { CanRestructure = true; ReturnType = typeof(Int64); } public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { return (arguments[0].GetIntValue(exm) != 0) ? arguments[1].GetIntValue(exm) : arguments[2].GetIntValue(exm); } } private sealed class TernaryIntStrStr : OperatorMethod { public TernaryIntStrStr() { CanRestructure = true; ReturnType = typeof(string); } public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false) { return (arguments[0].GetIntValue(exm) != 0) ? arguments[1].GetStrValue(exm) : arguments[2].GetStrValue(exm); } } #endregion } }