public PredicatePartsStageHelperObject(int id, int parent, PredicatePartType type, int level)
 {
     Id = id;
     Parent = parent;
     Type = type;
     Level = level;
 }
        private ForbidToJoinAnotherInfOrAuxVerb _getForbidToJoinAnotherInfinitiveOrAuxVerb(List<PredicatePartHelperObject> sourceElements, PredicatePartHelperObject element, PredicatePartType type, PredicatePartType getForbidFor)
        {
            Debug.Assert(type != PredicatePartType.AuxVerb);
            Debug.Assert(getForbidFor != PredicatePartType.Root);

            // фильтруем элементы группы, оставляем одни объекты типа type, и тот ряд ОЧ, в который входит текущий объект
            var typedElementsInGroup = sourceElements.FindAll(x => x.PartType == type && x.UPRowNr == element.UPRowNr);
            // если рассматриваем возможность присоединения ВГ, то разворачиваем ряд ОЧ, т.к. ВГ подсоединяется к основному слову вначале, а не в конце, как Инф
            if (getForbidFor == PredicatePartType.AuxVerb)
                typedElementsInGroup.Reverse();

            if (typedElementsInGroup.Count > 0)
                if (typedElementsInGroup.Last() == element)
                {
                    // Элемент последний/первый в ОЧ ряду. Пропуск
                    return ForbidToJoinAnotherInfOrAuxVerb.Undefined;
                }

            var forbidToJoin = true;
            // формируем список ОЧ-инфинитивов или других КСО, которые находятся справа (И) или слева(ВГ) от текущего рассматриваемого
            var searchedElements = new List<PredicatePartHelperObject>();
            switch (getForbidFor)
            {
                case PredicatePartType.Infinitive: searchedElements = typedElementsInGroup.FindAll(x => x.Order > element.Order); break;
                case PredicatePartType.AuxVerb: searchedElements= typedElementsInGroup.FindAll(x => x.Order < element.Order); break;
            }

            foreach (var nextTypedElement in searchedElements)
            {
                var canJoinTyped = false;
                switch (getForbidFor)
                {
                    case PredicatePartType.Infinitive: canJoinTyped = element.CanJoinAnotherInfinitive; break;
                    case PredicatePartType.AuxVerb: canJoinTyped = element.CanJoinAnotherAuxVerb; break;
                }

                var nextTypedElementCanJoin = false;
                switch (getForbidFor)
                {
                    case PredicatePartType.Infinitive: nextTypedElementCanJoin = nextTypedElement.CanJoinAnotherInfinitive; break;
                    case PredicatePartType.AuxVerb: nextTypedElementCanJoin = nextTypedElement.CanJoinAnotherAuxVerb; break;
                }

                var hasNextTypedElementChildren = sourceElements.FindAll(x => x.PartParentId == nextTypedElement.Id && x.PartType == getForbidFor).Count > 0;
                element.NextSameTypeElementHasChildren = hasNextTypedElementChildren;

                // если у элемента есть право на присоединение и у след. элемента есть потомки, то разрешаем
                if (canJoinTyped && hasNextTypedElementChildren)
                    forbidToJoin = false;
                else if (!nextTypedElementCanJoin)
                {
                    // если права нет, то это "обрыв" и дальше не продолаем
                    forbidToJoin = true;
                    break;
                }
            }

            return forbidToJoin ? ForbidToJoinAnotherInfOrAuxVerb.Forbid : ForbidToJoinAnotherInfOrAuxVerb.Allow;
        }