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