예제 #1
0
 /// <summary>
 /// Метод вычисления дубликатов подвыражений
 /// </summary>
 /// <param name="subexpressions">Список подвыражений</param>
 /// <param name="variables">Хранилище переменных</param>
 /// <param name="enableBooster">Флаг, отвечающий за включение ускорения вычислений</param>
 public void calculateDuplicates(List <Subexpression> subexpressions, VariablesStorage variables, bool enableBooster)
 {
     foreach (Subexpression subexpression in subexpressions)
     {
         if (subexpression.mustBePrecalculated)
         {
             subexpression.value = calculateSubexpressionValue(subexpression, variables, enableBooster);
         }
     }
 }
예제 #2
0
        /// <summary>
        /// Метод логирования переменных
        /// </summary>
        /// <param name="variablesStorage">Хранилище переменных</param>
        public void logVariables(VariablesStorage variablesStorage)
        {
            if (noLogMode)
            {
                return;
            }

            foreach (IntViewVariable intVariable in variablesStorage.intVariables)
            {
                loggerComponent.AppendText("Переменная: " + intVariable.name + ", значение: " + intVariable.value + "\n");
            }
            foreach (FuzzyViewVariable fuzzyVariable in variablesStorage.fuzzyVariables)
            {
                loggerComponent.AppendText("Переменная: " + fuzzyVariable.name + ", значение: " + fuzzyVariable.value + "\n");
            }
        }
예제 #3
0
 /// <summary>
 /// Метод подбора нечетких переменных по значениям.
 /// Используется при инициализации переменных, перед вычислением выражений ТО или ИНАЧЕ, и после обработки каждого из нечетких правил.
 /// Возвращает сущность <see cref="FuzzyVariableSelectionResult"/>.
 /// </summary>
 /// <param name="variables">Хранилище переменных</param>
 public FuzzyVariableSelectionResult makeSelection(VariablesStorage variables)
 {
     foreach (FuzzyViewVariable fvv in variables.fuzzyVariables)
     {
         if (fvv.fuzzyVariableId.HasValue)
         {
             continue;
         }
         fvv.fuzzyVariableId = getFuzzyVariableIdByName(fvv.value);
         if (!fvv.fuzzyVariableId.HasValue)
         {
             return(new FuzzyVariableSelectionResult(false, "Не найдена переменная с нечетким значением: " + fvv.value));
         }
     }
     return(new FuzzyVariableSelectionResult(true, null));
 }
        /// <summary>
        /// Метод получения представления нечекой переменной из лексемы.
        /// Возвращает представление нечеткой переменной <see cref="FuzzyViewVariable"/>
        /// </summary>
        /// <param name="lexeme">Лексема</param>
        /// <param name="variablesStorage">Хранилище переменных</param>
        public static FuzzyViewVariable getFuzzyVariableByLexeme(Lexeme lexeme, VariablesStorage variablesStorage)
        {
            if (lexeme == null || !LexemeTypes.IsIdentifier(lexeme.lexemeType))
            {
                return(null);
            }

            foreach (FuzzyViewVariable iv in variablesStorage.fuzzyVariables)
            {
                if (iv.name.Equals(lexeme.lexemeText))
                {
                    return(iv);
                }
            }

            return(null);
        }
예제 #5
0
        /// <summary>
        /// Метод логирования переменных с присвоенными им значениями
        /// </summary>
        /// <param name="variables">Хранилище переменных</param>
        /// <param name="showReassignmentInfo">true, если нужно указать информацию об уровне переопределения, false в противном случае</param>
        public void logAssignedVariables(VariablesStorage variables, bool showReassignmentInfo)
        {
            if (noLogMode)
            {
                return;
            }

            loggerComponent.AppendText("\n\n----------Текущие значения переменных:----------------\n");
            foreach (IntViewVariable iv in variables.intVariables)
            {
                loggerComponent.AppendText("Переменная: " + iv.name + ", значение: " + iv.value
                                           + (showReassignmentInfo ? ", переопределена в выражении: " + iv.firstReassignmentLevel : "") + "\n");
            }
            foreach (FuzzyViewVariable iv in variables.fuzzyVariables)
            {
                loggerComponent.AppendText("Переменная: " + iv.name + ", значение: " + iv.value
                                           + (showReassignmentInfo ? ", переопределена в выражении: " + iv.firstReassignmentLevel : "") + "\n");
            }
        }
        /// <summary>
        /// Метод выделения дубликатов подвыражений.
        /// Если выражение - дубликат, флаг mustBePrecalculated будет установлен в значение true.
        /// Флаг устанавливается для ВСЕХ подвыражений, включая первое.
        /// </summary>
        /// <param name="expressions">Список подвыражений</param>
        /// <param name="variablesStorage">Хранилище переменных</param>
        public static void markDuplicates(List <Subexpression> expressions, VariablesStorage variablesStorage)
        {
            List <Subexpression> deduplicatedExpressions = new List <Subexpression>();

            foreach (Subexpression exp in expressions)
            {
                bool duplicateFound = false;
                foreach (Subexpression dde in deduplicatedExpressions)
                {
                    if (exp.Equals(dde))
                    {
                        dde.mustBePrecalculated = true;
                        exp.mustBePrecalculated = true;
                        duplicateFound          = true;
                        //No need to break: we should add all same expressions with different levels
                    }
                }
                if (!duplicateFound)
                {
                    deduplicatedExpressions.Add(exp);
                }
            }

            //Checking semantic and filtering duplicates: if variable already reassigned, we should NOT add subexpression into duplicates
            foreach (Subexpression exp in expressions)
            {
                if (exp.mustBePrecalculated == true)
                {
                    List <AbstractViewVariable> abstractVariables = LexicalAnalysisService.getVariablesBySubexpression(exp, variablesStorage);

                    foreach (AbstractViewVariable av in abstractVariables)
                    {
                        if (av.firstReassignmentLevel != -1 && av.firstReassignmentLevel < exp.expressionLevel)
                        {
                            exp.mustBePrecalculated = false;
                            break;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Метод присваивания переменных.
        /// Изменяет значения в хранилище переменных.
        /// Выполняется для выражений ТО или ИНАЧЕ, а также после обработки каждого из нечетких правил.
        /// </summary>
        /// <param name="parserResult">Список лексем</param>
        /// <param name="variables">Хранилище переменных</param>
        /// <param name="subexpressionLevel">Уровень текущего подвыражения</param>
        //TODO: possible move to another or separate sevice
        //TODO: split into two methods: one for assign value, another for assign level
        public static void assignVariables(List <Lexeme> parserResult, VariablesStorage variables, int subexpressionLevel)
        {
            //Lexemes now stored as Identifier-Assign-(Value/Identifier)-Comma-Identifier-...
            Lexeme identifierSavior = null;

            for (int i = 0; i < parserResult.Count; i++)
            {
                Lexeme lex = parserResult[i];
                if (LexemeTypes.IsIdentifier(lex.lexemeType))
                {
                    if ((i != 0) && (parserResult[i - 1].lexemeType == LexemeType.Assign))
                    {
                        //В данном случае lex - это переменная ПОСЛЕ знака "="

                        //Пытаемся получить переменную ПОСЛЕ знака "=" как целочисленную
                        IntViewVariable intAfterVariable = getIntVariableByLexeme(lex, variables);
                        if (intAfterVariable != null)
                        {
                            bool found = false;
                            //Пытаемся получить переменную ДО знака "=" как целочисленную
                            foreach (IntViewVariable iv in variables.intVariables)
                            {
                                //Если нашли, ей нужно установить значение
                                if (iv.name.Equals(identifierSavior.lexemeText))
                                {
                                    iv.value = intAfterVariable.value;
                                    if (iv.firstReassignmentLevel == -1)
                                    {
                                        iv.firstReassignmentLevel = subexpressionLevel;
                                    }
                                    found = true;
                                    break;
                                }
                            }

                            //Если всё ещё не нашли, то...
                            if (!found)
                            {
                                //...пытаемся получить переменную ДО знака "=" как нечеткую
                                int levelSavior = -1;
                                foreach (FuzzyViewVariable fv in variables.fuzzyVariables)
                                {
                                    //Если нашли, её удаляем...
                                    if (fv.name.Equals(identifierSavior.lexemeText))
                                    {
                                        levelSavior = fv.firstReassignmentLevel;
                                        variables.fuzzyVariables.Remove(fv);
                                        found = true;
                                        break;
                                    }
                                }
                                //...и добавляем новую целочисленную
                                if (found)
                                {
                                    variables.intVariables.Add(new IntViewVariable(identifierSavior.lexemeText, intAfterVariable.value, levelSavior));
                                }
                            }

                            if (!found)
                            {
                                variables.intVariables.Add(new IntViewVariable(identifierSavior.lexemeText, intAfterVariable.value));
                            }
                        }
                        else
                        {
                            //Пытаемся получить переменную ПОСЛЕ знака "=" как нечеткую
                            FuzzyViewVariable fuzzyAfterVariable = getFuzzyVariableByLexeme(lex, variables);
                            if (fuzzyAfterVariable != null)
                            {
                                bool found = false;
                                //Пытаемся получить переменную ДО знака "=" как нечеткую
                                foreach (FuzzyViewVariable fv in variables.fuzzyVariables)
                                {
                                    //Если нашли, ей нужно установить значение
                                    if (fv.name.Equals(identifierSavior.lexemeText))
                                    {
                                        fv.value = fuzzyAfterVariable.value;
                                        if (fv.firstReassignmentLevel == -1)
                                        {
                                            fv.firstReassignmentLevel = subexpressionLevel;
                                        }
                                        found = true;
                                        break;
                                    }
                                }

                                //Если всё ещё не нашли, то...
                                if (!found)
                                {
                                    //...пытаемся получить переменную ДО знака "=" как целочисленную
                                    int levelSavior = -1;
                                    foreach (IntViewVariable iv in variables.intVariables)
                                    {
                                        //Если нашли, её удаляем...
                                        if (iv.name.Equals(identifierSavior.lexemeText))
                                        {
                                            variables.intVariables.Remove(iv);
                                            found = true;
                                            break;
                                        }
                                    }
                                    //...и добавляем новую нечеткую
                                    if (found)
                                    {
                                        variables.fuzzyVariables.Add(new FuzzyViewVariable(identifierSavior.lexemeText, fuzzyAfterVariable.value, levelSavior));
                                    }
                                }

                                if (!found)
                                {
                                    variables.fuzzyVariables.Add(new FuzzyViewVariable(identifierSavior.lexemeText, fuzzyAfterVariable.value));
                                }
                            }
                        }
                        identifierSavior = null;
                    }
                    else
                    {
                        //В данном случае мы только прочитали первый идентификатор
                        identifierSavior = lex;
                    }
                }
                else if (LexemeTypes.IsIntValue(lex.lexemeType))
                {
                    if (identifierSavior != null)
                    {
                        //TODO: move to helper method
                        bool assignedToExistingVariable = false;
                        foreach (IntViewVariable iv in variables.intVariables)
                        {
                            if (iv.name.Equals(identifierSavior.lexemeText))
                            {
                                iv.value = Convert.ToInt32(lex.lexemeText);
                                //Setting reassignment level to avoid marking some expressions as duplicates
                                if (iv.firstReassignmentLevel == -1)
                                {
                                    iv.firstReassignmentLevel = subexpressionLevel;
                                }
                                assignedToExistingVariable = true;
                                break;
                            }
                        }
                        if (!assignedToExistingVariable)
                        {
                            variables.intVariables.Add(new IntViewVariable(identifierSavior.lexemeText, Convert.ToInt32(lex.lexemeText)));
                        }
                        identifierSavior = null;
                    }
                }
                else if (LexemeTypes.IsFuzzyValue(lex.lexemeType))
                {
                    //TODO: move to helper method
                    bool assignedToExistingVariable = false;
                    foreach (FuzzyViewVariable iv in variables.fuzzyVariables)
                    {
                        if (iv.name.Equals(identifierSavior.lexemeText))
                        {
                            iv.value = lex.lexemeText;
                            //Setting reassignment level to avoid marking some expressions as duplicates
                            if (iv.firstReassignmentLevel == -1)
                            {
                                iv.firstReassignmentLevel = subexpressionLevel;
                            }
                            assignedToExistingVariable = true;
                            break;
                        }
                    }
                    if (!assignedToExistingVariable)
                    {
                        variables.fuzzyVariables.Add(new FuzzyViewVariable(identifierSavior.lexemeText, lex.lexemeText));
                    }
                    identifierSavior = null;
                }
            }
        }
        /// <summary>
        /// Метод получения списка абстрактных представлений переменных из подвыражения.
        /// Возврщает список абстрактных представлений переменных <see cref="AbstractViewVariable"/>
        /// </summary>
        /// <param name="subexpression">Подвыражение</param>
        /// <param name="variablesStorage">Хранилище переменных</param>
        public static List <AbstractViewVariable> getVariablesBySubexpression(Subexpression subexpression, VariablesStorage variablesStorage)
        {
            List <AbstractViewVariable> returnVariables = new List <AbstractViewVariable>();

            if (subexpression.isLeaf())
            {
                AbstractViewVariable ivFirst = getVariableByLexeme(subexpression.lexemeFirst, variablesStorage);
                if (ivFirst != null)
                {
                    returnVariables.Add(ivFirst);
                }
                AbstractViewVariable ivSecond = getVariableByLexeme(subexpression.lexemeSecond, variablesStorage);
                if (ivSecond != null)
                {
                    returnVariables.Add(ivSecond);
                }
            }
            else if (subexpression.isMixed())
            {
                returnVariables.AddRange(getVariablesBySubexpression(subexpression.subexpressionFirst, variablesStorage));
                AbstractViewVariable ivSecond = getVariableByLexeme(subexpression.lexemeSecond, variablesStorage);
                if (ivSecond != null)
                {
                    returnVariables.Add(ivSecond);
                }
            }
            else
            {
                returnVariables.AddRange(getVariablesBySubexpression(subexpression.subexpressionFirst, variablesStorage));
                returnVariables.AddRange(getVariablesBySubexpression(subexpression.subexpressionSecond, variablesStorage));
            }

            return(returnVariables);
        }
        /// <summary>
        /// Метод выполнения лексического анализа.
        /// Возвращает результат лексического анализа <see cref="LexicalAnalysisResult"/>
        /// </summary>
        /// <param name="parserResult">Список лексем</param>
        /// <param name="variables">Хранилище переменных</param>
        public static LexicalAnalysisResult makeSemanticAnalysis(List <Lexeme> parserResult, VariablesStorage variables)
        {
            LexicalAnalysisResult semanticResult = new LexicalAnalysisResult();

            semanticResult.isCorrect = true;
            semanticResult.output    = new List <string>();

            foreach (Lexeme lexeme in parserResult)
            {
                if (LexemeTypes.IsIdentifier(lexeme.lexemeType))
                {
                    bool permittedIdentifier = false;
                    //Searching identifier in int variables...
                    foreach (IntViewVariable v in variables.intVariables)
                    {
                        if (v.name.Equals(lexeme.lexemeText))
                        {
                            permittedIdentifier = true;
                            break;
                        }
                    }
                    //Searching identifier in fuzzy variables...
                    if (!permittedIdentifier)
                    {
                        foreach (FuzzyViewVariable v in variables.fuzzyVariables)
                        {
                            if (v.name.Equals(lexeme.lexemeText))
                            {
                                permittedIdentifier = true;
                                break;
                            }
                        }
                    }
                    if (!permittedIdentifier)
                    {
                        semanticResult.output.Add("Неизвестный идентификатор: " + lexeme.lexemeText + "\n");
                        semanticResult.isCorrect = false;
                    }
                }
            }

            return(semanticResult);
        }
예제 #10
0
        /// <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);
                }
            }
        }
 public IfStatement Build(VariablesStorage variables)
 {
     return(new IfStatement(_condition, _trueStatement, variables));
 }
예제 #12
0
        private void button_process_Click(object sender, EventArgs e)
        {
            var watch = Stopwatch.StartNew();

            loggingService           = new LoggingService(richTextBox_log);
            loggingService.noLogMode = checkBox_measureExecutionTime.Checked;
            clearWorkplace();

            //Init int and fuzzy variables
            VariablesStorage variablesStorage =
                InitVariablesService.initVariables(dataGridView_intVariables.Rows, dataGridView_intVariables.NewRowIndex, loggingService);

            //Select fuzzy variables by their names
            FuzzyVariableSelectionResult selectionResult = fuzzyVariableService.makeSelection(variablesStorage);

            if (!selectionResult.isSuccess)
            {
                loggingService.logFuzzySelectionError(selectionResult);
                return;
            }

            //Copy int and fuzzy variables into holder
            variablesStorage_holder.intVariables.AddRange(variablesStorage.intVariables);
            variablesStorage_holder.fuzzyVariables.AddRange(variablesStorage.fuzzyVariables);

            //Init expressions
            expressionsStorage.AddRange(
                InitExpressionsService.initExpressions(dataGridView_expressions.Rows, dataGridView_expressions.NewRowIndex, loggingService)
                );

            foreach (Expression expression in expressionsStorage)
            {
                //Checking IF expression
                List <Lexeme> ifParserResult = ParserService.parseIfExpression(expression.ifExpressionText);
                loggingService.logIfParser(expression.ifExpressionText, ifParserResult);

                //Checking parser result on fuzzy values existence
                FuzzyVariableSelectionResult ifSelectionResult = fuzzyVariableService.makeSelection(ifParserResult);
                if (!ifSelectionResult.isSuccess)
                {
                    loggingService.logFuzzySelectionError(ifSelectionResult);
                    return;
                }

                //Checking semantic
                LexicalAnalysisResult semanticResult = LexicalAnalysisService.makeSemanticAnalysis(ifParserResult, variablesStorage);
                loggingService.logLexicalAnalysis(semanticResult);

                //Next steps are available only if semantic analysis is correct
                if (!semanticResult.isCorrect)
                {
                    return;
                }

                //Sorting by reverse polish notation
                List <Lexeme> reversePolishNotationLexemeList = ReversePolishNotationService.createNotation(ifParserResult);
                loggingService.logReversePolishNotation(reversePolishNotationLexemeList);

                //Creating subexpressions
                List <Subexpression> currentSubexpressions = subexpressionService.createSubexpressionsList(reversePolishNotationLexemeList, expression.expressionLevel);
                loggingService.logSubexpressions(currentSubexpressions);
                subexpressions.AddRange(currentSubexpressions);

                //Checking THEN expression
                List <Lexeme> thenParserResult = ParserService.parseThenOrElseExpression(expression.thenExpressionText);
                loggingService.logThenOrElseParser(expression.thenExpressionText, thenParserResult, true);


                //Variable assignment
                //We should assign variables now to correctly mark duplicates
                //We have no idea now whether THEN or ELSE expression will be executed
                LexicalAnalysisService.assignVariables(thenParserResult, variablesStorage, expression.expressionLevel);
                loggingService.logAssignedVariables(variablesStorage, true);

                //Select fuzzy variables by their names
                FuzzyVariableSelectionResult thenSelectionResult = fuzzyVariableService.makeSelection(variablesStorage);
                if (!thenSelectionResult.isSuccess)
                {
                    loggingService.logFuzzySelectionError(thenSelectionResult);
                    return;
                }

                //Checking ELSE expression
                List <Lexeme> elseParserResult = ParserService.parseThenOrElseExpression(expression.elseExpressionText);
                loggingService.logThenOrElseParser(expression.elseExpressionText, elseParserResult, false);

                LexicalAnalysisService.assignVariables(elseParserResult, variablesStorage, expression.expressionLevel);
                loggingService.logAssignedVariables(variablesStorage, true);

                //Select fuzzy variables by their names
                FuzzyVariableSelectionResult elseSelectionResult = fuzzyVariableService.makeSelection(variablesStorage);
                if (!elseSelectionResult.isSuccess)
                {
                    loggingService.logFuzzySelectionError(elseSelectionResult);
                    return;
                }
            }

            //Marking duplicates
            DuplicateExpressionService.markDuplicates(subexpressions, variablesStorage);
            loggingService.logDuplicates(subexpressions);

            if (!checkBox_disableBoosters.Checked)
            {
                //Precalculating duplicates
                subexpressionService.calculateDuplicates(subexpressions, variablesStorage, !checkBox_disableBoosters.Checked);
                loggingService.logDuplicatesValues(subexpressions);
            }

            //Restore int variables storage to init state
            variablesStorage.Clear();
            variablesStorage.intVariables.AddRange(variablesStorage_holder.intVariables);
            variablesStorage.fuzzyVariables.AddRange(variablesStorage_holder.fuzzyVariables);

            //Calculating major subexpressions one by one
            //TODO: check level and compare it with local counter to avoid wrong order
            foreach (Subexpression subexpression in subexpressions)
            {
                if (subexpression.major)
                {
                    //Calculate subexpression
                    subexpression.value = subexpressionService.calculateSubexpressionValue(subexpression, variablesStorage, !checkBox_disableBoosters.Checked);

                    //Prepare int variables storage to next iteration
                    List <Lexeme> parserResult;
                    if (subexpression.value.Value)
                    {
                        parserResult = ParserService.parseThenOrElseExpression(expressionsStorage[subexpression.expressionLevel - 1].thenExpressionText);
                    }
                    else
                    {
                        parserResult = ParserService.parseThenOrElseExpression(expressionsStorage[subexpression.expressionLevel - 1].elseExpressionText);
                    }
                    LexicalAnalysisService.assignVariables(parserResult, variablesStorage, subexpression.expressionLevel);

                    //Select fuzzy variables by their names
                    FuzzyVariableSelectionResult sfvSelectionResult = fuzzyVariableService.makeSelection(variablesStorage);
                    if (!sfvSelectionResult.isSuccess)
                    {
                        loggingService.logFuzzySelectionError(sfvSelectionResult);
                        return;
                    }
                }
            }

            loggingService.logString("------========РЕЗУЛЬТАТЫ:========---------\n");
            loggingService.logSubexpressions(subexpressions);

            loggingService.noLogMode = false;
            loggingService.logAssignedVariables(variablesStorage, false);

            watch.Stop();
            if (checkBox_measureExecutionTime.Checked)
            {
                loggingService.logExecutionTime(watch.ElapsedMilliseconds);
            }
        }