Esempio n. 1
0
 /// <summary>
 /// Конструктор обычного подвыражения
 /// </summary>
 /// <param name="subexpressionFirst">Первое подвыражение</param>
 /// <param name="operation">Операция</param>
 /// <param name="subexpressionSecond">Второе подвыражение</param>
 /// <param name="expressionLevel">Порядковый номер выражения</param>
 public Subexpression(Subexpression subexpressionFirst, OperationEnum operation, Subexpression subexpressionSecond, int expressionLevel)
 {
     this.subexpressionFirst  = subexpressionFirst;
     this.operation           = operation;
     this.subexpressionSecond = subexpressionSecond;
     this.expressionLevel     = expressionLevel;
 }
        /// <summary>
        /// Метод создания списка подвыражений из списка лексем
        /// </summary>
        /// <param name="lexemes">Список лексем</param>
        /// <param name="expressionLevel">Порядковый номер выражения</param>
        public List <Subexpression> createSubexpressionsList(List <Lexeme> lexemes, int expressionLevel)
        {
            List <Subexpression>  subexpressions      = new List <Subexpression>();
            Stack <Subexpression> subexpressionsStack = new Stack <Subexpression>();
            Stack <Lexeme>        lexemesStack        = new Stack <Lexeme>();

            foreach (Lexeme lex in lexemes)
            {
                if (LexemeTypes.IsValue(lex.lexemeType) || LexemeTypes.IsIdentifier(lex.lexemeType))
                {
                    lexemesStack.Push(lex);
                }
                else if (LexemeTypes.IsOperation(lex.lexemeType))
                {
                    if (lexemesStack.Count >= 2)
                    {
                        Lexeme        lexemeSecond  = lexemesStack.Pop();
                        Lexeme        lexemeFirst   = lexemesStack.Pop();
                        Subexpression subexpression = new Subexpression(lexemeFirst, getOperationByLexeme(lex.lexemeText), lexemeSecond, expressionLevel);
                        subexpressions.Add(subexpression);
                        subexpressionsStack.Push(subexpression);
                    }
                    else if (subexpressionsStack.Count >= 2)
                    {
                        Subexpression subexpressionSecond = subexpressionsStack.Pop();
                        Subexpression subexpressionFirst  = subexpressionsStack.Pop();
                        Subexpression subexpression       = new Subexpression(subexpressionFirst, getOperationByLexeme(lex.lexemeText), subexpressionSecond, expressionLevel);
                        subexpressions.Add(subexpression);
                        subexpressionsStack.Push(subexpression);
                    }
                    else if (lexemesStack.Count == 1 && subexpressionsStack.Count == 1)
                    {
                        Subexpression subexpressionFirst = subexpressionsStack.Pop();
                        Lexeme        lexemeSecond       = lexemesStack.Pop();
                        Subexpression subexpression      = new Subexpression(subexpressionFirst, getOperationByLexeme(lex.lexemeText), lexemeSecond, expressionLevel);
                        subexpressions.Add(subexpression);
                        subexpressionsStack.Push(subexpression);
                    }
                }
            }

            //Last expression in list is always major
            if (subexpressions.Count > 0)
            {
                subexpressions[subexpressions.Count - 1].major = true;
            }

            return(subexpressions);
        }
 /// <summary>
 /// Метод поиска подвыражений, не влияющих на общий результат.
 /// Возвращает null, если подвыражение следует считать в общем потоке, и true или false (как значения подвыражения), если удалось отбросить не влияющую на результат часть
 /// </summary>
 /// <param name="subexpression">Подвыражение</param>
 public bool?calculationBooster(Subexpression subexpression)
 {
     if (subexpression.subexpressionFirst.value.HasValue)
     {
         if (subexpression.operation == OperationEnum.And)
         {
             if (subexpression.subexpressionFirst.value.Value.Equals(false))
             {
                 return(false);
             }
         }
         else if (subexpression.operation == OperationEnum.Or)
         {
             if (subexpression.subexpressionFirst.value.Value.Equals(true))
             {
                 return(true);
             }
         }
     }
     return(null);
 }
        /// <summary>
        /// Метод вычисления одного подвыражения.
        /// Возвращает значение подвыражения - true или false
        /// </summary>
        /// <param name="subexpression">Подвыражение</param>
        /// <param name="variablesStorage">Хранилище переменных</param>
        /// <param name="enableBooster">Флаг, отвечающий за включение ускорения вычислений</param>
        public bool calculateSubexpressionValue(Subexpression subexpression, VariablesStorage variablesStorage, bool enableBooster)
        {
            //If subexpression already has the value, simply return it
            if (subexpression.value.HasValue)
            {
                return(subexpression.value.Value);
            }

            if (subexpression.isLeaf())
            {
                int?   intValueFirst = null, intValueSecond = null;
                string stringValueFirst = null, stringValueSecond = null;

                //Checking first lexeme in subexpression
                if (LexemeTypes.IsIntValue(subexpression.lexemeFirst.lexemeType))
                {
                    intValueFirst = Convert.ToInt32(subexpression.lexemeFirst.lexemeText);
                }
                else if (LexemeTypes.IsFuzzyValue(subexpression.lexemeFirst.lexemeType))
                {
                    stringValueFirst = subexpression.lexemeFirst.lexemeText;
                }
                else if (LexemeTypes.IsIdentifier(subexpression.lexemeFirst.lexemeType))
                {
                    var obj = InitVariablesService.getValueFromVariablesStorage(subexpression.lexemeFirst.lexemeText, variablesStorage);
                    if ((obj == null) || (obj is int?))
                    {
                        intValueFirst = Convert.ToInt32(obj);
                    }
                    else
                    {
                        stringValueFirst = Convert.ToString(obj);
                    }
                }

                //Checking second lexeme in subexpression
                if (LexemeTypes.IsIntValue(subexpression.lexemeSecond.lexemeType))
                {
                    intValueSecond = Convert.ToInt32(subexpression.lexemeSecond.lexemeText);
                }
                else if (LexemeTypes.IsFuzzyValue(subexpression.lexemeSecond.lexemeType))
                {
                    stringValueSecond = subexpression.lexemeSecond.lexemeText;
                }
                else if (LexemeTypes.IsIdentifier(subexpression.lexemeSecond.lexemeType))
                {
                    var obj = InitVariablesService.getValueFromVariablesStorage(subexpression.lexemeSecond.lexemeText, variablesStorage);
                    if ((obj == null) || (obj is int?))
                    {
                        intValueSecond = Convert.ToInt32(obj);
                    }
                    else
                    {
                        stringValueSecond = Convert.ToString(obj);
                    }
                }

                //If subexpression has uninitialized variables, we couldn't evaluate it. Return false in this case
                if ((!intValueFirst.HasValue && stringValueFirst == null) || (!intValueSecond.HasValue && stringValueSecond == null))
                {
                    return(false);
                }

                switch (subexpression.operation)
                {
                //It is not OK but possible to use AND and OR operaions in leaf expression
                case OperationEnum.And:
                    if (intValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return((intValueFirst.Value != 0) && (intValueSecond.Value != 0));
                        }
                        else if (stringValueSecond != null)
                        {
                            return((intValueFirst.Value != 0) && (stringValueSecond != null));
                        }
                    }
                    else if (stringValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return((stringValueFirst != null) && (intValueSecond.Value != 0));
                        }
                        else if (stringValueSecond != null)
                        {
                            return((stringValueFirst != null) && (stringValueSecond != null));
                        }
                    }
                    return(false);

                case OperationEnum.Or:
                    if (intValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return((intValueFirst.Value != 0) || (intValueSecond.Value != 0));
                        }
                        else if (stringValueSecond != null)
                        {
                            return((intValueFirst.Value != 0) || (stringValueSecond != null));
                        }
                    }
                    else if (stringValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return((stringValueFirst != null) || (intValueSecond.Value != 0));
                        }
                        else if (stringValueSecond != null)
                        {
                            return((stringValueFirst != null) || (stringValueSecond != null));
                        }
                    }
                    return(false);

                //Comparison operations are fully OK
                case OperationEnum.Equal:
                    if (intValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(intValueFirst.Value == intValueSecond.Value);
                        }
                        else if (stringValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyEquals(intValueFirst.Value, stringValueSecond));
                        }
                    }
                    else if (stringValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyEquals(intValueSecond.Value, stringValueFirst));
                        }
                        else if (stringValueSecond != null)
                        {
                            return(stringValueFirst == stringValueSecond);
                        }
                    }
                    return(false);

                case OperationEnum.NotEqual:
                    if (intValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(intValueFirst.Value != intValueSecond.Value);
                        }
                        else if (stringValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyNotEquals(intValueFirst.Value, stringValueSecond));
                        }
                    }
                    else if (stringValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyNotEquals(intValueSecond.Value, stringValueFirst));
                        }
                        else if (stringValueSecond != null)
                        {
                            return(stringValueFirst != stringValueSecond);
                        }
                    }
                    return(false);

                case OperationEnum.More:
                    if (intValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(intValueFirst.Value > intValueSecond.Value);
                        }
                        else if (stringValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyMore(intValueFirst.Value, stringValueSecond));
                        }
                    }
                    else if (stringValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyMore(stringValueFirst, intValueSecond.Value));
                        }
                        else if (stringValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyMore(stringValueFirst, stringValueSecond));
                        }
                    }
                    return(false);

                case OperationEnum.MoreOrEqual:
                    if (intValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(intValueFirst.Value >= intValueSecond.Value);
                        }
                        else if (stringValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyMoreOrEquals(intValueFirst.Value, stringValueSecond));
                        }
                    }
                    else if (stringValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyMoreOrEquals(stringValueFirst, intValueSecond.Value));
                        }
                        else if (stringValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyMoreOrEquals(stringValueFirst, stringValueSecond));
                        }
                    }
                    return(false);

                case OperationEnum.Less:
                    if (intValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(intValueFirst.Value < intValueSecond.Value);
                        }
                        else if (stringValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyLess(intValueFirst.Value, stringValueSecond));
                        }
                    }
                    else if (stringValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyLess(stringValueFirst, intValueSecond.Value));
                        }
                        else if (stringValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyLess(stringValueFirst, stringValueSecond));
                        }
                    }
                    return(false);

                case OperationEnum.LessOrEqual:
                    if (intValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(intValueFirst.Value <= intValueSecond.Value);
                        }
                        else if (stringValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyLessOrEquals(intValueFirst.Value, stringValueSecond));
                        }
                    }
                    else if (stringValueFirst != null)
                    {
                        if (intValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyLessOrEquals(stringValueFirst, intValueSecond.Value));
                        }
                        else if (stringValueSecond != null)
                        {
                            return(fuzzyVariableService.fuzzyLessOrEquals(stringValueFirst, stringValueSecond));
                        }
                    }
                    return(false);

                //Rest operations are not allowed, and in this case false will be returned
                default:
                    return(false);
                }
            }
            else if (subexpression.isMixed())
            {
                if (enableBooster)
                {
                    bool?preBooster = calculationBooster(subexpression);
                    if (preBooster.HasValue)
                    {
                        return(preBooster.Value);
                    }
                }

                //Calculate first subexpression value if it doesn't exists
                if (!subexpression.subexpressionFirst.value.HasValue)
                {
                    subexpression.subexpressionFirst.value = calculateSubexpressionValue(subexpression.subexpressionFirst, variablesStorage, enableBooster);
                }

                if (enableBooster)
                {
                    bool?secondBooster = calculationBooster(subexpression);
                    if (secondBooster.HasValue)
                    {
                        return(secondBooster.Value);
                    }
                }

                int?   intValueSecond    = null;
                string stringValueSecond = null;

                //Checking second lexeme in subexpression
                if (LexemeTypes.IsIntValue(subexpression.lexemeSecond.lexemeType))
                {
                    intValueSecond = Convert.ToInt32(subexpression.lexemeSecond.lexemeText);
                }
                else if (LexemeTypes.IsFuzzyValue(subexpression.lexemeSecond.lexemeType))
                {
                    stringValueSecond = subexpression.lexemeSecond.lexemeText;
                }
                else if (LexemeTypes.IsIdentifier(subexpression.lexemeSecond.lexemeType))
                {
                    var obj = InitVariablesService.getValueFromVariablesStorage(subexpression.lexemeSecond.lexemeText, variablesStorage);
                    if ((obj == null) || (obj is int?))
                    {
                        intValueSecond = Convert.ToInt32(obj);
                    }
                    else
                    {
                        stringValueSecond = Convert.ToString(obj);
                    }
                }

                //If subexpression has uninitialized variables, we couldn't evaluate it. Return false in this case
                if (!intValueSecond.HasValue && stringValueSecond == null)
                {
                    return(false);
                }

                switch (subexpression.operation)
                {
                //AND and OR operaions are fully OK in mixed subexpression
                case OperationEnum.And:
                    if (intValueSecond != null)
                    {
                        return(subexpression.subexpressionFirst.value.Value && (intValueSecond.Value != 0));
                    }
                    else if (stringValueSecond != null)
                    {
                        return(subexpression.subexpressionFirst.value.Value && (stringValueSecond != null));
                    }
                    else
                    {
                        return(false);
                    }

                case OperationEnum.Or:
                    if (intValueSecond != null)
                    {
                        return(subexpression.subexpressionFirst.value.Value || (intValueSecond.Value != 0));
                    }
                    else if (stringValueSecond != null)
                    {
                        return(subexpression.subexpressionFirst.value.Value || (stringValueSecond != null));
                    }
                    else
                    {
                        return(false);
                    }

                //Comparison operations are strange but possible
                case OperationEnum.Equal:
                    if (intValueSecond != null)
                    {
                        return(subexpression.subexpressionFirst.value.Value == (intValueSecond.Value != 0));
                    }
                    else if (stringValueSecond != null)
                    {
                        return(subexpression.subexpressionFirst.value.Value == (stringValueSecond != null));
                    }
                    else
                    {
                        return(false);
                    }

                case OperationEnum.NotEqual:
                    if (intValueSecond != null)
                    {
                        return(subexpression.subexpressionFirst.value.Value != (intValueSecond.Value != 0));
                    }
                    else if (stringValueSecond != null)
                    {
                        return(subexpression.subexpressionFirst.value.Value != (stringValueSecond != null));
                    }
                    else
                    {
                        return(false);
                    }

                //Rest operations are not allowed, and in this case false will be returned
                default:
                    return(false);
                }
            }
            //Ordinary subexpression are here
            else
            {
                if (enableBooster)
                {
                    bool?preBooster = calculationBooster(subexpression);
                    if (preBooster.HasValue)
                    {
                        return(preBooster.Value);
                    }
                }

                //Calculate first subexpression value if it doesn't exists
                if (!subexpression.subexpressionFirst.value.HasValue)
                {
                    subexpression.subexpressionFirst.value = calculateSubexpressionValue(subexpression.subexpressionFirst, variablesStorage, enableBooster);
                }

                if (enableBooster)
                {
                    bool?secondBooster = calculationBooster(subexpression);
                    if (secondBooster.HasValue)
                    {
                        return(secondBooster.Value);
                    }
                }

                //Calculate second subexpression value if it doesn't exists
                if (!subexpression.subexpressionSecond.value.HasValue)
                {
                    subexpression.subexpressionSecond.value = calculateSubexpressionValue(subexpression.subexpressionSecond, variablesStorage, enableBooster);
                }

                switch (subexpression.operation)
                {
                //AND and OR operaions are fully OK in mixed subexpression
                case OperationEnum.And:
                    return(subexpression.subexpressionFirst.value.Value && subexpression.subexpressionSecond.value.Value);

                case OperationEnum.Or:
                    return(subexpression.subexpressionFirst.value.Value || subexpression.subexpressionSecond.value.Value);

                //Comparison operations are strange but possible
                case OperationEnum.Equal:
                    return(subexpression.subexpressionFirst.value.Value == subexpression.subexpressionSecond.value.Value);

                case OperationEnum.NotEqual:
                    return(subexpression.subexpressionFirst.value.Value != subexpression.subexpressionSecond.value.Value);

                //Rest operations are not allowed, and in this case false will be returned
                default:
                    return(false);
                }
            }
        }