bool CAnalyticFormBuilder::HasDeclinableSynNounInInstrumentalis(const CWord& _W) const
{
    for (CWord::SHomIt it = _W.IterHomonyms(); it.Ok(); ++it)
        if (IsSynNoun(*it) && it->HasGrammem(gInstrumental) && !it->HasGrammem(gNominative))
            return true;
    return false;
}
bool CAnalyticFormBuilder::HasInfinitive(const CWord& W)
{
    for (CWord::SHomIt it = W.IterHomonyms(); it.Ok(); ++it)
        if (it->HasGrammem(gInfinitive))
            return true;

    return false;
}
bool CAnalyticFormBuilder::HasCompar(const CWord& W)
{
    for (CWord::SHomIt it = W.IterHomonyms(); it.Ok(); ++it)
        if (it->IsFullAdjective() && it->HasGrammem(gComparative))
            return true;

    return false;
}
bool CAnalyticFormBuilder::HasPredik(const CWord& W)
{
    for (CWord::SHomIt it = W.IterHomonyms(); it.Ok(); ++it)
        if (!it->Grammems.IsIndeclinable()) //  "бух","спасибо" не строятся с анал. формами
            if (it->HasGrammem(gPraedic))
                return true;

    return false;
}
bool CAnalyticFormBuilder::CheckAnalyticalVerbForm(int iVWrd, int iSWrd)
{
    int VerbHomNo;
    yvector<int> AnalyticHom;

    bool b_AddAuxVerbHom;
    if (!IsAnalyticalVerbForm(iVWrd, iSWrd, VerbHomNo, AnalyticHom, b_AddAuxVerbHom))
        return false;

    if (AnalyticHom.size() == 0)
        return false;

    CWord& _Be = m_Words.GetWord(m_ClauseWords.at(iVWrd));
    CWord& _Predik = m_Words.GetWord(m_ClauseWords.at(iSWrd));

    //nim: в версии Диалинга у потенциального предиката (второй компоненты аналитической формы)
    //удалялись все омонимы, которые не могли образовать настоящую аналитическую форму,
    //например, для "хорошо" удалялись омонимы "Н" и "ЧАСТ".
    //в текущей версии покамест оставляем все омонимы. :nim

    for (size_t j = 0; j < AnalyticHom.size(); j++) {
        ChangeGrammemsAsAnalyticForm(_Predik.GetRusHomonym(AnalyticHom[j]), _Be.GetRusHomonym(VerbHomNo));
    }

    if (b_AddAuxVerbHom) {
        THomonymPtr pAuxHom = _Be.GetRusHomonym(VerbHomNo).Clone();
        pAuxHom->Grammems.Add(gAuxVerb);
        _Be.AddRusHomonym(pAuxHom);
        VerbHomNo = _Be.HasPOSi(gAuxVerb);
    } else
        _Be.GetRusHomonym(VerbHomNo).Grammems.Add(gAuxVerb);

    //удаляются омонимы не AuxVerb
    //так для слф. "были" будет убит омоним "быль"
    //пример: "были спровоцированы скандалы"
    yvector<int> HomsToDel;
    for (CWord::SHomIt it = _Be.IterHomonyms(); it.Ok(); ++it)
        if (!it->HasGrammem(gAuxVerb))
            HomsToDel.push_back(it.GetID());

    YASSERT(HomsToDel.size() < _Be.GetRusHomonymsCount());
    for (size_t i = 0; i < HomsToDel.size(); ++i)
        _Be.DeleteHomonym(HomsToDel[i]);
    //так как если вызывается из фрагментации и с синтаксисом, то
    //уже все символы были построены, а мы удаляем омоним с приписанными терминалами
    _Be.UniteHomonymsTerminalSymbols();
    for (size_t j = 0; j < AnalyticHom.size(); j++)
        _Predik.GetRusHomonym(AnalyticHom[j]).SetAnalyticMainVerbHom(&(_Be.GetRusHomonym(VerbHomNo)));

    return true;
}
bool CAnalyticFormBuilder::HasAnalyticalBe(const CWord& _W) const
{
    //NB! в настоящем варианте парсера нет словаря оборотов, поэтому проверка слова на оборот временно отключена
    // если мы попали на оборот(например, "может быть"), тогда не будем строить здесь анал. форму.
    //if (_W.IsInOborot()) return false;

    // "быто" предсказывается как "быть"
    //if (_W.m_bPredicted) return false;
    //NB! пока предсказание отсутствует в парсере

    //if ( _W.HasPOS(UnknownPOS) ) return false;
    if (_W.HasUnknownPOS()) return false;

    for (CWord::SHomIt it = _W.IterHomonyms(); it.Ok(); ++it) {
        bool is_verb = it->IsPersonalVerb();
        if (is_verb && !it->IsPresentTense() && it->Lemma == kByt)
            return true;
        if ((is_verb || it->HasGrammem(gInfinitive)) && it->Lemma == kStat)
            return true;
    }
    return false;
}
/*
  building of verb analytical forms: auxiliary can be "byt'" (to be) or "stat'" (to become) [translit]
*/
void CAnalyticFormBuilder::BuildAnalyticalVerbForms()
{
    //auxiliary verb number in chain of wordforms - the first part of an.f.
    int iBe = -1;
    //vector of potential predicates for second part
    CAnalyticalFormVars v_AnalyticalFormVars;
    BuildAnalyticalVerbFormsZaplata2();

    for (size_t WordNo = 0; WordNo < m_ClauseWords.size(); WordNo++) {
        const CWord& _Form = m_Words.GetWord(m_ClauseWords.at(WordNo));
        if (!_Form.IsAnalyticVerbForm()) {
            if (!m_ClauseWords.at(WordNo).m_bOriginalWord)
                continue;
            const Wtroka& s_lem = _Form.IterHomonyms()->Lemma;
            //looking for verbs "to be" or "to become"
            if (HasAnalyticalBe(_Form) && iBe == -1) {
                iBe = WordNo;
                continue;
            }

            if (HasInfinitive(_Form)) {
                v_AnalyticalFormVars.push_back(SAnalyticalFormVariant(WordNo, _Form.GetRusHomonymsCount(), SAnalyticalFormVariant::Infinitive, s_lem, AllHomonymsArePredicates(_Form)));
                continue;
            }

            if (HasPredik(_Form)) {
                v_AnalyticalFormVars.push_back(SAnalyticalFormVariant(WordNo, _Form.GetRusHomonymsCount(), SAnalyticalFormVariant::Predikative, s_lem, AllHomonymsArePredicates(_Form)));
                continue;
            }

            if (HasShortParticipleOrAdj(_Form)) {
                v_AnalyticalFormVars.push_back(SAnalyticalFormVariant(WordNo, _Form.GetRusHomonymsCount(), SAnalyticalFormVariant::Short_Form, s_lem, AllHomonymsArePredicates(_Form)));
                continue;
            }
            //looking for comparative form
            if (HasCompar(_Form))
                v_AnalyticalFormVars.push_back(SAnalyticalFormVariant(WordNo, _Form.GetRusHomonymsCount(), SAnalyticalFormVariant::Comp_Adj, s_lem, AllHomonymsArePredicates(_Form)));
        }
    }

    if (iBe != -1 && v_AnalyticalFormVars.size() > 0) {
            {
                //правило для цепочки {"быть"(буд.), предикатив (омонимичный), инфинитив (нс)}, тогда строим ан.ф. с инфинитивом
                //"Мальчик будет горько плакать"
                int DummyHomNo;
                bool bDummyAuxVHom;
                yvector<int> dummyVector;
                if    ((2 == v_AnalyticalFormVars.size())
                        &&    (iBe < v_AnalyticalFormVars[0].iWordNum)
                        &&  !v_AnalyticalFormVars[0].bAllHomPredik
                        &&  SAnalyticalFormVariant::Predikative == v_AnalyticalFormVars[0].ePos
                        &&  SAnalyticalFormVariant::Infinitive == v_AnalyticalFormVars[1].ePos

                        &&  IsAnalyticalVerbForm(iBe, v_AnalyticalFormVars[0].iWordNum, DummyHomNo, dummyVector, bDummyAuxVHom)
                        &&  IsAnalyticalVerbForm(iBe, v_AnalyticalFormVars[1].iWordNum, DummyHomNo, dummyVector, bDummyAuxVHom)
                    ) {
                        bool bFoundChain = true;
                        for (int mm = 0; mm < iBe; mm++) {
                            const CWord& _Form = m_Words.GetWord(m_ClauseWords.at(mm));
                            for (CWord::SHomIt it = _Form.IterHomonyms(); it.Ok(); ++it)
                                if (it->HasGrammem(gDative))
                                    bFoundChain = false;
                        }

                        if (bFoundChain)
                            // удаляем вариант омонимичного предикатива, если есть вариант будущего времени
                            v_AnalyticalFormVars.erase(v_AnalyticalFormVars.begin());
                    }

                //  конец  подслучая "Мальчик будет горько плакать"
            };

            //проверить на возможное вхождение компоненты аналитической формы в синтаксическую группу:
            //"был о нем"
            //CheckGroupsForAnalyticalVerbForms(v_AnalyticalFormVars, PrCl); : DIALING
            //в текущей версии синтаксиса именных групп покамест нет

            if (0 == v_AnalyticalFormVars.size()) return;

            /*разбираем случай "он был больше учителем, чем шофером", где не надо строить
              аналитическую форму со сравн. степенью, хотя, в принципе, ей ничего не мешает.

              Формально:
              Если у нас только одна гипотеза ("сравн. степени"), если после нее стоит существительное
              в творительном падеже, тогда  анал. форму строит не надо.
               Сокирко. 3 мая 2001
            */
            if (v_AnalyticalFormVars.size() == 1)
                if (SAnalyticalFormVariant::Comp_Adj == v_AnalyticalFormVars[0].ePos)
                    if (CheckComparativeZAPLATAForAnalyticalForm(v_AnalyticalFormVars[0].iWordNum))
                        return;

            //установить порядок на гипотезах (см. operator<);
            std::sort(v_AnalyticalFormVars.begin(), v_AnalyticalFormVars.end());

            for (size_t k = 0; k < v_AnalyticalFormVars.size(); k++)
                if (CheckAnalyticalVerbForm(iBe, v_AnalyticalFormVars[k].iWordNum)) {
                    //Stroka n_str = m_Words[iBe].m_strWord;
                    //n_str = n_str + "-" + m_Words[v_AnalyticalFormVars[k].iWordNum].m_strWord;
                    //m_Words[v_AnalyticalFormVars[k].iWordNum].SetWordStr(n_str);
                    //m_Words[v_AnalyticalFormVars[k].iWordNum].m_bAnalyticalForm = true;

                    break;
                }
    }
}