void BuildUniversal_FinishWord(TextInLanguage.SyntaxLayout.Sentence sentence, ref string word, int startIndex, int endIndex)
        {
            if (word != string.Empty)
            {
                var props = new TextInLanguage.SyntaxLayout.Word.Properties();

                sentence.AddWord(word, startIndex, endIndex, props);
                word = string.Empty;
            }
        }
        // Универсальный метод постройки. Может работать не для всех языков, но работает для большинства, это точно
        protected TextInLanguage.SyntaxLayout BuildUniversal(string text, string wordLetters, string sentenceBeginingLetters, string sentenceEndingLetters, char exclamationEnding, char questionEnding)
        {
            TextInLanguage.SyntaxLayout result = new TextInLanguage.SyntaxLayout();

            TextInLanguage.SyntaxLayout.Sentence currentSentence = null;
            string currentWord           = string.Empty;
            int    currentWordStartIndex = 0;
            int    lastWordLetterIndex   = -1;

            for (int letterIdx = 0; letterIdx < text.Length; letterIdx++)
            {
                bool isLastLetter = letterIdx == text.Length - 1;
                char letter       = text[letterIdx];

                if (currentSentence == null)
                {
                    // Ищем начало предложения. Оно должно начинаться с буквы
                    if (wordLetters.Contains(letter))
                    {
                        currentSentence = result.AddSentence(letterIdx);
                    }
                }

                if (currentSentence != null)
                {
                    // Если это буква из слова
                    if (wordLetters.Contains(letter))
                    {
                        // Если слово только началось - запишем текущий индекс как начальный для этого слова
                        if (currentWord == string.Empty)
                        {
                            currentWordStartIndex = letterIdx;
                        }

                        // Добавим в текущее слово эту букву
                        currentWord += letter;

                        lastWordLetterIndex = letterIdx;
                    }
                    else
                    {
                        // Текущий символ - не часть слова
                        // В этом случае заканчиваем текущее набранное слово, если таковое есть
                        BuildUniversal_FinishWord(currentSentence, ref currentWord, currentWordStartIndex, lastWordLetterIndex);
                    }

                    bool isLastLetterOrSentenceBegining = isLastLetter || sentenceBeginingLetters.Contains(letter);

                    // Если это конец предложения, или это последний символ во всем тексте
                    if (sentenceEndingLetters.Contains(letter) || isLastLetterOrSentenceBegining)
                    {
                        // Если было накопленное слово - закончим его
                        BuildUniversal_FinishWord(currentSentence, ref currentWord, currentWordStartIndex, lastWordLetterIndex);
                        currentSentence.LastIndex = lastWordLetterIndex;

                        var props = new TextInLanguage.SyntaxLayout.Sentence.Properties();
                        props.kind = TextInLanguage.SyntaxLayout.Sentence.Kind.Declarative;

                        if (!isLastLetterOrSentenceBegining)
                        {
                            if (letter == exclamationEnding)
                            {
                                props.kind = TextInLanguage.SyntaxLayout.Sentence.Kind.Exclamation;
                            }
                            else if (letter == questionEnding)
                            {
                                props.kind = TextInLanguage.SyntaxLayout.Sentence.Kind.Question;
                            }
                        }

                        currentSentence.Props = props;

                        // Предложение закончилось, теперь ищем следующее предложение
                        currentSentence = null;
                    }
                }
            }

            result.EraseEmptySentences();
            return(result);
        }