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::HasShortParticipleOrAdj(const CWord& _W) const
{
    for (CWord::SHomIt it = _W.IterHomonyms(); it.Ok(); ++it)
        if (it->IsShortAdjectiveOrParticiple())
            return true;
    return false;
}
void CPrimitiveGroup::ResetGrammems()
{
    Grammems.Reset();
    for (CWord::SHomIt it = m_pWord->IterHomonyms(); it.Ok(); ++it)
        if (it->HasTerminalSymbol(GetActiveSymbol()))
            Grammems |= it->Grammems;
}
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::AllHomonymsArePredicates(const CWord& W) const
{
    const TGramBitSet VerbGerundPraedic(gVerb, gGerund, gPraedic);
    for (CWord::SHomIt it = W.IterHomonyms(); it.Ok(); ++it) {
        if (it->HasAnyOfPOS(VerbGerundPraedic) || it->IsShortAdjectiveOrParticiple())
             continue;
        //verbs that can not be predicates or an.f.
        if (!TAnalyticFormPredicates::Has(it->Lemma))
            return false;
     }
    return true;
}
Exemple #8
0
const CHomonym* THomonymInflector::SelectBestHomonym(const CWord& word, const TGramBitSet& desired) {
    const CHomonym* res = NULL;
    size_t bestCommon = 0;
    for (CWord::SHomIt it = word.IterHomonyms(); it.Ok(); ++it) {
        TGramBitSet curGram = SelectBestHomoform(*it, desired);
        size_t curCommon = (curGram & desired).count();
        if (res == NULL || bestCommon < curCommon) {
            res = &*it;
            bestCommon = curCommon;
        }
    }
    return res;
}
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;
}
static bool FindBestHomonym(const CWord& word, TWtringBuf lemma, TKeyWordType kwtype, THomonymGrammems grammems, int& homId) {
    // search if we already have a multiword homonym with such text
    bool found = false;
    bool foundSameKwType = false;
    for (CWord::SHomIt it = word.IterHomonyms(); it.Ok(); ++it)
        if (it->CHomonymBase::GetLemma() == lemma) {
            if (it->HasKWType(kwtype, KW_DICT)) {
                if (it->Grammems == grammems) {
                    homId = it.GetID();     // prefer homonyms with same kwtype and same grammems
                    return true;
                } else if (!foundSameKwType) {
                    homId = it.GetID(); // prefer homonyms with same kwtype
                    found = true;
                    foundSameKwType = true;
                }
            } else  if (!found) {
                homId = it.GetID();   // otherwise, return the first one having @lemma text
                found = true;
            }
        }

    return found;
}
/*
  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;
                }
    }
}
//check an agreement between aux. verbs and predicates of analitical form.
bool CAnalyticFormBuilder::IsAnalyticalVerbForm(int iVerbWrd, int iSWrd, int& VerbHomNo,
                                                yvector<int>& AnalyticHom, bool& b_AddAuxVerbHom)
{
    b_AddAuxVerbHom = false;
    AnalyticHom.clear();

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

    //с предикативными значениями "много" и "мало" анал. форм не строить : DIALING
    //с предикативными значениями "много" и "мало" анал. форм строится, но клонируется омоним для вспомогательного глагола
    //if ( ( m_Words[iSWrd].FindLemma("МНОГО") || m_Words[iSWrd].FindLemma("МАЛО") ) && ... )
    if (_Predik.HasPOS(gNumeral) && _Predik.HasPOS(gPraedic))
            b_AddAuxVerbHom = true;

    //14.07.04: отсутствие синтаксиса порождает заплатку:
    //если у потенциального предиката есть омоним Noun, то добавить омоним AuxVerb для вспомогательного глагола,
    //в противном случае, просто изменить часть речи на AuxVerb.
    if (_Predik.HasMorphNoun())
        b_AddAuxVerbHom = true;

    //masks used later (to avoid constructing them repeatedly in loop)
    const TGramBitSet Verb_Infinitive(gVerb, gInfinitive),
                      Infinitive_Imperfect(gInfinitive, gImperfect),
                      Person3_Singular(gPerson3, gSingular),
                      Infinitive_Gerund(gInfinitive, gGerund);

    for (CWord::SHomIt it = _Be.IterHomonyms(); it.Ok(); ++it) {
        VerbHomNo = it.GetID();
        const CHomonym& VerbHom = _Be.GetRusHomonym(VerbHomNo);

        if (VerbHom.Lemma == kByt || (VerbHom.Lemma == kStat && VerbHom.HasAnyOfPOS(Verb_Infinitive))) {
            for (CWord::SHomIt it_predik = _Predik.IterHomonyms(); it_predik.Ok(); ++it_predik) {
                int j = it_predik.GetID();

                const CHomonym& ShortFormHom = _Predik.GetRusHomonym(j);
                if (ShortFormHom.Grammems.HasAll(Infinitive_Imperfect) && (VerbHom.IsFutureTense() || VerbHom.Lemma == kStat))
                    AnalyticHom.push_back(j);

                else if ((ShortFormHom.HasGrammem(gPraedic)) &&
                         (VerbHom.HasGrammem(gNeuter) || (VerbHom.IsFutureTense() && VerbHom.Grammems.HasAll(Person3_Singular))))
                    AnalyticHom.push_back(j);

                else if (ShortFormHom.HasGrammem(gComparative) && ShortFormHom.IsFullAdjective())
                    AnalyticHom.push_back(j);

                else if (ShortFormHom.IsShortAdjectiveOrParticiple()) {
                    // "была", "стал", "был", "было" ...
                    if ((VerbHom.HasGrammem(gSingular) && VerbHom.IsPastTense() &&
                         ShortFormHom.HasGrammem(gSingular) &&
                         (VerbHom.Grammems.All() & ShortFormHom.Grammems.All()).HasAny(NSpike::AllGenders))
                        || (VerbHom.HasGrammem(gPlural) && ShortFormHom.HasGrammem(gPlural))
                        || (!VerbHom.IsPastTense() && VerbHom.HasGrammem(gSingular) && ShortFormHom.HasGrammem(gSingular))
                        || VerbHom.Grammems.HasAny(Infinitive_Gerund))

                        AnalyticHom.push_back(j);
                }
            }
            return AnalyticHom.size() > 0;
        }
    }
    return false;
}