// 二項演算
		static public ExpressionToken OperateBinary(ExpressionToken value1, ExpressionToken token, ExpressionToken value2)
		{
			return new ExpressionToken("", false, ExpressionToken.TokenType.Number, 0, CalcBinary(value1.variable, token, value2.variable));
		}
		// 二項演算の計算
		static object CalcBinary(object value1, ExpressionToken token, object value2)
		{
			switch (token.name)
			{
				case Prod:		// *
				case Div:		// /
				case Mod:		// %
				case Plus:		// +
				case Minus:		// -
				case Greater:	// >
				case Less:		// <
				case GreaterEq:	// >=
				case LessEq:	// <=
					return CalcBinaryNumber(value1, token, value2);
				case EqEq:		// ==
				case NotEq:		// !=
					return CalcBinaryEq(value1, token, value2);
				case And:		// &&
				case Or:		// ||
					return CalcBinaryAndOr(value1, token, value2);
				default:
					throw new Exception(LanguageErrorMsg.LocalizeTextFormat(Utage.ErrorMsg.ExpressionOperator, token.name));
			}
		}
Beispiel #3
0
        //逆ポーランド記法に変換
        List <ExpressionToken> ToReversePolishNotationSub(List <ExpressionToken> tokens)
        {
            List <ExpressionToken> expList = new List <ExpressionToken>();            //返還後のリスト
            //式を逆ポーランド記法に変換
            Stack <ExpressionToken> tmpStack = new Stack <ExpressionToken>();         //演算子用のスタック

            foreach (ExpressionToken token in tokens)
            {
                try
                {
                    switch (token.Type)
                    {
                    case ExpressionToken.TokenType.Lpa:                                 //左括弧
                        tmpStack.Push(token);
                        break;

                    case ExpressionToken.TokenType.Rpa:                                 //右括弧
                    {
                        while (tmpStack.Count != 0)
                        {
                            ExpressionToken last = tmpStack.Peek();
                            if (ExpressionToken.TokenType.Lpa == last.Type)
                            {
                                tmpStack.Pop();
                                break;
                            }
                            expList.Add(tmpStack.Pop());
                        }
                    }
                    break;

                    case ExpressionToken.TokenType.Binary:                              //演算子
                    case ExpressionToken.TokenType.Unary:
                    case ExpressionToken.TokenType.Substitution:
                    case ExpressionToken.TokenType.Function:
                    {
                        ExpressionToken last = tmpStack.Peek();
                        while (tmpStack.Count != 0 && (token.Priority > last.Priority))
                        {
                            if (ExpressionToken.TokenType.Lpa == last.Type)
                            {
                                break;
                            }
                            expList.Add(last);
                            tmpStack.Pop();
                            last = tmpStack.Peek();
                        }
                        tmpStack.Push(token);
                    }
                    break;

                    case ExpressionToken.TokenType.Number:                              //変数
                    case ExpressionToken.TokenType.Value:                               //値
                        expList.Add(token);
                        break;

                    case ExpressionToken.TokenType.Comma:                               //カンマ
                        // スタックのトップのトークンが左括弧になるまで
                        // スタック上の演算子を出力キューにポップし続ける
                        while (true)
                        {
                            ExpressionToken last = tmpStack.Peek();
                            if (ExpressionToken.TokenType.Lpa == last.Type)
                            {
                                break;
                            }
                            expList.Add(tmpStack.Pop());
                        }
                        break;

                    default:
                        AddErrorMsg(LanguageErrorMsg.LocalizeTextFormat(Utage.ErrorMsg.UnknownType, token.Type.ToString()));
                        break;
                    }
                }
                catch (System.Exception e)
                {
                    AddErrorMsg(e.ToString());
                }
            }
            return(expList);
        }
		// 単項演算の計算
		static object CalcUnary(object value, ExpressionToken token)
		{
			switch (token.name)
			{
				case Not:		// !
					if (value is bool) return !(bool)value;
					else
					{
						throw new Exception(LanguageErrorMsg.LocalizeTextFormat(Utage.ErrorMsg.ExpressionOperator, token.name));
					}
				case Plus:		// +
					if (value is float) return value;
					else if (value is int) return value;
					else
					{
						throw new Exception(LanguageErrorMsg.LocalizeTextFormat(Utage.ErrorMsg.ExpressionOperator, token.name));
					}
				case Minus:		// -
					if (value is float) return -(float)value;
					else if (value is int) return -(int)value;
					else
					{
						throw new Exception(LanguageErrorMsg.LocalizeTextFormat(Utage.ErrorMsg.ExpressionOperator, token.name));
					}
				default:
					throw new Exception(LanguageErrorMsg.LocalizeTextFormat(Utage.ErrorMsg.ExpressionOperator, token.name));
			}
		}
		// 二項演算の計算(&&や||などの論理式)
		static object CalcBinaryAndOr(object value1, ExpressionToken token, object value2)
		{
			if (value1 is bool)
			{
				if (value2 is bool) return CalcBinaryAndOrSub((bool)value1, token, (bool)value2);
			}
			throw new Exception(LanguageErrorMsg.LocalizeTextFormat(Utage.ErrorMsg.ExpressionOperator, token.name));
		}
		//関数名であればトークン作成
		static bool TryParseFunction(string name, out ExpressionToken token)
		{
			switch (name)
			{
				case FuncRandom:
					token = new ExpressionToken(name, false, ExpressionToken.TokenType.Function, 0);
					token.numFunctionArg = 2;
					return true;
				case FuncRandomF:
					token = new ExpressionToken(name, false, ExpressionToken.TokenType.Function, 0);
					token.numFunctionArg = 2;
					return true;
				default:
					token = null;
					return false;
			}
		}
		// 演算式の結果を計算
		object Calc(System.Func<string, object, bool> callbackSetValue )
		{
			try
			{
				///逆ポーランド式の演算
				Stack<ExpressionToken> values = new Stack<ExpressionToken>();
				ExpressionToken value1;
				ExpressionToken value2;
				foreach (ExpressionToken token in tokens)
				{
					switch (token.Type)
					{
						case ExpressionToken.TokenType.Substitution:	//代入演算
							value2 = values.Pop();
							value1 = values.Pop();
							values.Push(ExpressionToken.OperateSubstition(value1, token, value2, callbackSetValue));
							break;
						case ExpressionToken.TokenType.Unary:			//単項演算
							values.Push(ExpressionToken.OperateUnary(values.Pop(), token));
							break;
						case ExpressionToken.TokenType.Binary:			//二項演算
							value2 = values.Pop();
							value1 = values.Pop();
							values.Push(ExpressionToken.OperateBinary(value1, token, value2));
							break;
						case ExpressionToken.TokenType.Number:
						case ExpressionToken.TokenType.Value:
							values.Push(token);
							break;
						case ExpressionToken.TokenType.Function:		//関数
							{
								int num = token.NumFunctionArg;
								ExpressionToken[] args = new ExpressionToken[num];
								for (int i = 0; i < num; ++i)
								{
									args[num-i-1] = values.Pop();
								}
								values.Push(ExpressionToken.OperateFunction(token, args));
							}
							break;
						default:
							break;
					}
				}
				if (values.Count != 1)
				{
					throw new Exception(LanguageErrorMsg.LocalizeTextFormat(Utage.ErrorMsg.ExpIllegal));
				}
				return values.Peek().Variable;
			}
			catch(Exception e)
			{
				Debug.LogError(e.Message + e.StackTrace );
				AddErrorMsg(e.Message);
				return null;
			}
		}
		// 二項演算の計算(==や!=などの比較演算)
		static object CalcBinaryEq(object value1, ExpressionToken token, object value2)
		{
			if (value1 is int)
			{
				if (value2 is int) return CalcBinaryEqSub((int)value1, token, (int)value2);
				else if (value2 is float) return CalcBinaryEqSub((int)value1, token, (float)value2);
			}
			else if (value1 is float)
			{
				if (value2 is int) return CalcBinaryEqSub((float)value1, token, (int)value2);
				else if (value2 is float) return CalcBinaryEqSub((float)value1, token, (float)value2);
			}
			else if (value1 is bool)
			{
				if (value2 is bool) return CalcBinaryEqSub((bool)value1, token, (bool)value2);
			}
			else if (value1 is string)
			{
				if (value2 is string) return CalcBinaryEqSub((string)value1, token, (string)value2);
			}
			throw new Exception(LanguageErrorMsg.LocalizeTextFormat(Utage.ErrorMsg.ExpressionOperator, token.name));
		}
Beispiel #9
0
        // 演算式の結果を計算
        object Calc(System.Func <string, object, bool> callbackSetValue)
        {
            try
            {
                ///逆ポーランド式の演算
                Stack <ExpressionToken> values = new Stack <ExpressionToken>();
                ExpressionToken         value1;
                ExpressionToken         value2;
                foreach (ExpressionToken token in tokens)
                {
                    switch (token.Type)
                    {
                    case ExpressionToken.TokenType.Substitution:                                //代入演算
                        value2 = values.Pop();
                        value1 = values.Pop();
                        values.Push(ExpressionToken.OperateSubstition(value1, token, value2, callbackSetValue));
                        break;

                    case ExpressionToken.TokenType.Unary:                                               //単項演算
                        values.Push(ExpressionToken.OperateUnary(values.Pop(), token));
                        break;

                    case ExpressionToken.TokenType.Binary:                                              //二項演算
                        value2 = values.Pop();
                        value1 = values.Pop();
                        values.Push(ExpressionToken.OperateBinary(value1, token, value2));
                        break;

                    case ExpressionToken.TokenType.Number:
                    case ExpressionToken.TokenType.Value:
                        values.Push(token);
                        break;

                    case ExpressionToken.TokenType.Function:                                            //関数
                    {
                        int num = token.NumFunctionArg;
                        ExpressionToken[] args = new ExpressionToken[num];
                        for (int i = 0; i < num; ++i)
                        {
                            args[num - i - 1] = values.Pop();
                        }
                        values.Push(ExpressionToken.OperateFunction(token, args));
                    }
                    break;

                    default:
                        break;
                    }
                }
                if (values.Count != 1)
                {
                    throw new Exception(LanguageErrorMsg.LocalizeTextFormat(Utage.ErrorMsg.ExpIllegal));
                }
                return(values.Peek().Variable);
            }
            catch (Exception e)
            {
                Debug.LogError(e.Message + e.StackTrace);
                AddErrorMsg(e.Message);
                return(null);
            }
        }
Beispiel #10
0
        // 式を演算要素別に分解
        static List <ExpressionToken> SplitToken(string exp)
        {
            List <ExpressionToken> tokens = new List <ExpressionToken>();            //演算式

            tokens.Add(ExpressionToken.LpaToken);
            int    index       = 0;
            string strToken    = "";                            //直前の文字列
            bool   isValueMode = false;                         //直前のトークンが数値(変数)か、演算子か

            while (index < exp.Length)
            {
                char c = exp[index];
                if (char.IsWhiteSpace(c) || c == ',')
                {
                    //空白・区切り文字なので、直前の文字列をトークンとして分割
                    if (!string.IsNullOrEmpty(strToken))
                    {
                        tokens.Add(ExpressionToken.CreateToken(strToken));
                        isValueMode = true;
                    }
                    strToken = "";
                    index++;
                    continue;
                }

                //演算子が来たかチェック
                ExpressionToken operatior = ExpressionToken.FindOperator(exp, index);
                if (operatior == null)
                {
                    //演算子はなかった。一文字シフト
                    strToken += c;
                    index++;
                }
                else
                {
                    //演算子発見・直前の文字列をトークンとして分割
                    if (!string.IsNullOrEmpty(strToken))
                    {
                        tokens.Add(ExpressionToken.CreateToken(strToken));
                        isValueMode = true;
                    }

                    //演算子をトークンとして追加
                    if (!isValueMode && operatior.Name == ExpressionToken.Minus)
                    {
                        //単項演算子のマイナスとして登録(二項演算子ではなく)
                        tokens.Add(ExpressionToken.UniMinus);
                        isValueMode = true;
                    }
                    else if (!isValueMode && operatior.Name == ExpressionToken.Plus)
                    {
                        //単項演算子のプラスとして登録(二項演算子ではなく)
                        tokens.Add(ExpressionToken.UniPlus);
                        isValueMode = true;
                    }
                    else
                    {
                        //見つかった演算子を追加
                        tokens.Add(operatior);
                        if (operatior.Type != ExpressionToken.TokenType.Lpa && operatior.Type != ExpressionToken.TokenType.Rpa)
                        {
                            isValueMode = false;
                        }
                    }
                    strToken = "";
                    index   += operatior.Name.Length;
                }
            }
            if (!string.IsNullOrEmpty(strToken))
            {
                tokens.Add(ExpressionToken.CreateToken(strToken));
            }
            tokens.Add(ExpressionToken.RpaToken);
            return(tokens);
        }
Beispiel #11
0
 // 二項演算
 static public ExpressionToken OperateBinary(ExpressionToken value1, ExpressionToken token, ExpressionToken value2)
 {
     return(new ExpressionToken("", false, ExpressionToken.TokenType.Number, 0, CalcBinary(value1.variable, token, value2.variable)));
 }
Beispiel #12
0
 // 単項演算
 static public ExpressionToken OperateUnary(ExpressionToken value, ExpressionToken token)
 {
     return(new ExpressionToken("", false, ExpressionToken.TokenType.Number, 0, CalcUnary(value.variable, token)));
 }
Beispiel #13
0
 // 代入演算
 static public ExpressionToken OperateSubstition(ExpressionToken value1, ExpressionToken token, ExpressionToken value2, System.Func <string, object, bool> callbackSetValue)
 {
     value1.variable = CalcSubstition(value1.variable, token, value2.variable);
     //変数なので外部の代入処理
     if (value1.type == ExpressionToken.TokenType.Value)
     {
         if (!callbackSetValue(value1.name, value1.variable))
         {
             throw new Exception(LanguageErrorMsg.LocalizeTextFormat(Utage.ErrorMsg.ExpressionOperateSubstition, token.name, value1.variable));
         }
     }
     return(value1);
 }
		static object CalcBinaryNumberSub(float value1, ExpressionToken token, float value2)
		{
			switch (token.name)
			{
				case Prod: return (value1 * value2);
				case Div: return (value1 / value2);
				case Mod: return (value1 % value2);
				case Plus: return (value1 + value2);
				case Minus: return (value1 - value2);
				case Greater: return (value1 > value2);
				case Less: return (value1 < value2);
				case GreaterEq: return (value1 >= value2);
				case LessEq: return (value1 <= value2);
				default:
					throw new Exception(LanguageErrorMsg.LocalizeTextFormat(Utage.ErrorMsg.ExpressionOperator, token.name));
			}
		}
		// 代入演算
		static public ExpressionToken OperateSubstition(ExpressionToken value1, ExpressionToken token, ExpressionToken value2, System.Func<string, object, bool> callbackSetValue)
		{
			value1.variable = CalcSubstition(value1.variable, token, value2.variable);
			//変数なので外部の代入処理
			if (value1.type == ExpressionToken.TokenType.Value )
			{
				if (!callbackSetValue(value1.name, value1.variable))
				{
					throw new Exception(LanguageErrorMsg.LocalizeTextFormat(Utage.ErrorMsg.ExpressionOperateSubstition, token.name,value1.variable));
				}
			}
			return value1;
		}
		static object CalcBinaryNumberSub(bool value1, ExpressionToken token, string value2)
		{
			switch (token.name)
			{
				case Plus: return (value1 + value2);
				default:
					throw new Exception(LanguageErrorMsg.LocalizeTextFormat(Utage.ErrorMsg.ExpressionOperator, token.name));
			}
		}
		static object CalcSubstitionSub(float value1, ExpressionToken token, int value2)
		{
			switch (token.name)
			{
				case PlusEq:	return (value1 + value2);
				case MinusEq:	return (value1 - value2);
				case ProdEq:	return (value1 * value2);
				case DivEq:		return (value1 / value2);
				case ModEq:		return (value1 % value2);
				default:
					throw new Exception(LanguageErrorMsg.LocalizeTextFormat(Utage.ErrorMsg.ExpressionOperator, token.name));
			}
		}
		static object CalcBinaryEqSub(string value1, ExpressionToken token, string value2)
		{
			switch (token.name)
			{
				case EqEq: return (value1 == value2);
				case NotEq: return (value1 != value2);
				default:
					throw new Exception(LanguageErrorMsg.LocalizeTextFormat(Utage.ErrorMsg.ExpressionOperator, token.name));
			}
		}
		static object CalcSubstitionSub(string value1, ExpressionToken token, float value2)
		{
			switch (token.name)
			{
				case PlusEq: return (value1 + value2);
				default:
					throw new Exception(LanguageErrorMsg.LocalizeTextFormat(Utage.ErrorMsg.ExpressionOperator, token.name));
			}
		}
		// 二項演算の計算(&&や||などの論理式)
		static object CalcBinaryAndOrSub(bool value1, ExpressionToken token, bool value2)
		{
			switch (token.name)
			{
				case And: return (value1 && value2);
				case Or: return (value1 || value2);
				default:
					throw new Exception(LanguageErrorMsg.LocalizeTextFormat(Utage.ErrorMsg.ExpressionOperator, token.name));
			}
		}
		// 単項演算
		static public ExpressionToken OperateUnary(ExpressionToken value, ExpressionToken token)
		{
			return new ExpressionToken("", false, ExpressionToken.TokenType.Number, 0, CalcUnary(value.variable, token));
		}
		// 関数演算
		static public ExpressionToken OperateFunction(ExpressionToken token, ExpressionToken[] args)
		{
			switch (token.name)
			{
				case FuncRandom:
					{
						int random = UnityEngine.Random.Range(ExpressionCast.ToInt(args[0].variable), ExpressionCast.ToInt(args[1].variable)+1);
						return new ExpressionToken("", false, ExpressionToken.TokenType.Number, 0, random);
					}
				case FuncRandomF:
					{
						float random = UnityEngine.Random.Range(ExpressionCast.ToFloat(args[0].variable), ExpressionCast.ToFloat(args[1].variable));
						return new ExpressionToken("", false, ExpressionToken.TokenType.Number, 0, random);
					}
				default:
					throw new Exception("Unkonw Function :" + token.name);
			}
		}
Beispiel #23
0
        // 式を演算要素別に分解
        static List <ExpressionToken> SplitToken(string exp)
        {
            List <ExpressionToken> tokens = new List <ExpressionToken>();            //演算式

            tokens.Add(ExpressionToken.LpaToken);
            int    index    = 0;
            string strToken = "";                               //直前の文字列

            while (index < exp.Length)
            {
                char c = exp[index];

                bool       isSkipped       = false;
                const char StringSeparator = '\"';
                const char ArraySeparator0 = '[';
                const char ArraySeparator1 = ']';
                switch (c)
                {
                case StringSeparator:
                    SkipGroup(StringSeparator, StringSeparator, ref strToken, exp, ref index);
                    isSkipped = true;
                    tokens.Add(ExpressionToken.CreateToken(strToken));
                    strToken = "";
                    break;

                case ArraySeparator0:
                    SkipGroup(ArraySeparator0, ArraySeparator1, ref strToken, exp, ref index);
                    isSkipped = true;
                    break;

                default:
                    break;
                }
                if (isSkipped)
                {
                    continue;
                }

                if (char.IsWhiteSpace(c))
                {
                    //空白・区切り文字なので、直前の文字列をトークンとして分割
                    if (!string.IsNullOrEmpty(strToken))
                    {
                        tokens.Add(ExpressionToken.CreateToken(strToken));
                    }
                    strToken = "";
                    index++;
                    continue;
                }

                //演算子が来たかチェック
                ExpressionToken operatior = ExpressionToken.FindOperator(exp, index);
                if (operatior == null)
                {
                    //演算子はなかった。一文字シフト
                    strToken += c;
                    index++;
                }
                else
                {
                    //演算子発見・直前の文字列をトークンとして分割
                    if (!string.IsNullOrEmpty(strToken))
                    {
                        var token = ExpressionToken.CreateToken(strToken);
                        tokens.Add(token);
                    }

                    bool isValueLastToken = tokens.Count > 0 && tokens[tokens.Count - 1].IsValueType;
                    //演算子をトークンとして追加
                    if (!isValueLastToken && operatior.Name == ExpressionToken.Minus)
                    {
                        //単項演算子のマイナスとして登録(二項演算子ではなく)
                        tokens.Add(ExpressionToken.UniMinus);
                    }
                    else if (!isValueLastToken && operatior.Name == ExpressionToken.Plus)
                    {
                        //単項演算子のプラスとして登録(二項演算子ではなく)
                        tokens.Add(ExpressionToken.UniPlus);
                    }
                    else
                    {
                        //見つかった演算子を追加
                        tokens.Add(operatior);
                    }
                    strToken = "";
                    index   += operatior.Name.Length;
                }
            }
            if (!string.IsNullOrEmpty(strToken))
            {
                tokens.Add(ExpressionToken.CreateToken(strToken));
            }
            tokens.Add(ExpressionToken.RpaToken);
            return(tokens);
        }