/// <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); } } }
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); } }