// Лексический анализ с элементами семантики (для простоты кода) public static void LexicalAnalysis(Elements allElements, ref Diagram diagram) { Diagram = diagram; try { // Для классов и интерфейсов var curElements = allElements.Classes; var elementsCount = curElements.Count; for (var i = 0; i < elementsCount; i++) { var element = curElements[i]; var elementId = element.Id; var elementName = element.Name; var elementType = element.IsInterface ? "интерфейс" : "класс"; var upperElementType = elementType.Substring(0, 1).ToUpper() + elementType.Substring(1); // Проверка наличия связей (семантика) Checkers.CheckConnectionExistence(allElements, element, upperElementType); // Если есть protected, смотрим, есть ли потомки if (element.Attributes.Find(a => a.Visibility == Visibility.@protected) != null || element.Operations.Find(a => a.Visibility == Visibility.@protected) != null) { if (allElements.Classes.Find(a => a.GeneralClassesIdxs.Contains(elementId)) == null) { diagram.Mistakes.Add(new Mistake(2, $"{upperElementType} \"{elementName}\" с элементами \"protected\" не имеет потомков", element.Box, ALL_MISTAKES.CD_NO_CHILDREN)); } } // Проверка имени класса (интерфейса) Checkers.CheckName(elementName, elementType, element.Box); // Проверка наличия атрибутов и операторов var attributes = element.Attributes; var attributesCount = attributes.Count; var operations = element.Operations; var operationsCount = operations.Count; if (attributesCount == 0) { if (operationsCount == 0) { diagram.Mistakes.Add(new Mistake(2, $"{upperElementType} \"{elementName}\" должен иметь хотя бы один атрибут или операцию", element.Box, ALL_MISTAKES.CD_EMPTY_CLASS)); continue; } else { // Нет раздела с атрибутами diagram.Mistakes.Add(new Mistake(0, $"{upperElementType} \"{elementName}\" не имеет раздела с атрибутами", element.Box, ALL_MISTAKES.CD_MUST_BE_ATTRIB)); } } // Рассматриваем атрибуты for (var j = 0; j < attributesCount; j++) { var attribute = attributes[j]; // Проверка имени атрибута Checkers.CheckName(attribute.Name, "атрибут", element.Box); // Проверка типа атрибута Checkers.CheckType(attribute.DataTypeId); } // Рассматриваем операции for (var j = 0; j < operationsCount; j++) { var operation = operations[j]; var operationName = operation.Name; // Проверяем название операции var isConstrDestr = Checkers.CheckOperationName(operation, elementName, elementType, element.Box); // Проверяем типы параметров var paramsCount = operation.Parameters.Count; for (var k = 0; k < paramsCount; k++) { Checkers.CheckType(operation.Parameters[k].DataTypeId); } // Синтаксическая часть // Возвращаемое значение if ((isConstrDestr.Item1 || isConstrDestr.Item2) && operation.ReturnDataTypeId != "") { var typeStr = isConstrDestr.Item1 ? "Конструктор" : "Деструктор"; diagram.Mistakes.Add(new Mistake(2, $"{typeStr} \"{operationName}\" имеет возвращаемый тип ({elementType} \"{elementName}\")", element.Box, ALL_MISTAKES.CD_HAS_OUTPUT_TYPE)); } if (!isConstrDestr.Item1 && !isConstrDestr.Item2 && operation.ReturnDataTypeId == "") { diagram.Mistakes.Add(new Mistake(1, $"Не указан возвращаемый тип операции \"{operationName}\" ({elementType} \"{elementName}\")", element.Box, ALL_MISTAKES.CD_HAS_NOT_OUTPUT_TYPE)); } } } // Для перечислений var enumElements = allElements.Enumerations; elementsCount = enumElements.Count; for (var i = 0; i < elementsCount; i++) { var enumeration = allElements.Enumerations[i]; var enumerationId = enumeration.Id; var enumerationName = enumeration.Name; // Проверка наличия связей (семантика) var dependency = allElements.Dependences.Find(a => a.ClientElementId == enumerationId || a.SupplierElementId == enumerationId); if (dependency == null) { diagram.Mistakes.Add(new Mistake(2, $"Перечисление \"{enumerationName}\" не имеет допустимых связей", enumeration.Box, ALL_MISTAKES.CD_NO_AVAILABLE_LINKS)); } Checkers.CheckName(enumerationName, "перечисление", enumeration.Box); } // Комментарии в скобках {} var commentsCount = allElements.Comments.Count; for (var i = 0; i < commentsCount; i++) { Checkers.CheckComment(allElements.Comments[i]); } } catch (Exception ex) { Main.MainFormInstance.Invoke(new Action(() => { MessageBox.Show("Ошибка", "Ошибка в LexicalAnalysis: " + ex.Message, MessageBoxButtons.OK, MessageBoxIcon.Error); })); } }