예제 #1
0
static void MergeGrammems(THomonymGrammems& dst, const TGramBitSet& art_grammems, const TGramBitSet& newPos)
{
    // first, reset Part Of Speech if any
    if (newPos.HasAny(TMorph::AllPOS()))
        dst.SetPOS(newPos);
    else if (art_grammems.HasAny(TMorph::AllPOS()))
        dst.SetPOS(art_grammems);

    // take other grammems from @art_grammems if any
    TGramBitSet other = art_grammems & ~TMorph::AllPOS();
    if (other.any()) {
        // if there is a form with such grammems - just leave it alone and drop the rest ones
        bool found = false;
        for (THomonymGrammems::TFormIter it = dst.IterForms(); it.Ok(); ++it)
            if (it->HasAll(other)) {
                dst.ResetSingleForm(*it);
                found = true;
            }

        if (!found) {
            // otherwise merge all forms and replace grammems by classes
            TGramBitSet newForm = dst.All();
            newForm.ReplaceByMaskIfAny(art_grammems, NSpike::AllCases);
            newForm.ReplaceByMaskIfAny(art_grammems, NSpike::AllGenders);
            newForm.ReplaceByMaskIfAny(art_grammems, NSpike::AllNumbers);
            const TGramBitSet anim(gAnimated, gInanimated);
            newForm.ReplaceByMaskIfAny(art_grammems, anim);
            newForm.ReplaceByMaskIfAny(art_grammems, NSpike::AllTimes);
            newForm.ReplaceByMaskIfAny(art_grammems, NSpike::AllPersons);
            // just add the rest non-classified grammems
            static const TGramBitSet nonclassified = ~(NSpike::AllCases | NSpike::AllGenders | NSpike::AllNumbers |
                                                       anim | NSpike::AllTimes | NSpike::AllPersons);
            newForm |= art_grammems & nonclassified;
            dst.Reset(newForm);
        }
    }

    // if we still do not known POS, apply some workarounds:
    if (dst.GetPOS().none()) {
        dst.SetPOS(TGramBitSet(gSubstantive));
        if (!dst.HasAny(NSpike::AllCases))
            dst.Add(NSpike::AllCases);
        if (!dst.HasAny(NSpike::AllGenders))
            dst.Add(NSpike::AllGenders);
        if (!dst.HasAny(NSpike::AllNumbers))
            dst.Add(NSpike::AllNumbers);
        }

    // set a noun or adj without additional grammem as indeclinable
    if (!dst.HasAny(~TMorph::AllPOS()) &&
        (art_grammems.Has(gSubstantive) || TMorph::IsFullAdjective(art_grammems)))
        dst.Add(NSpike::AllCases | NSpike::AllGenders | NSpike::AllNumbers);

}
예제 #2
0
SWordHomonymNum CMultiWordCreator::AddMultiWordInt(CWordSequence* ws, bool takeOnwership,
                                                   const TGramBitSet& newPos, const CWordsPair& searchAreaWP)
{
    SWordHomonymNum wh = ws->GetMainWord();
    Wtroka stmp;
    SWordHomonymNum newWH;
    CWord* pNewWord = GetWordForMultiWord(*ws, stmp, newWH);

    pNewWord->m_SourceWords.SetPair(ws->FirstWord(), ws->LastWord());

    TGramBitSet art_grammems;      // output grammems of article
    Wtroka article_title;
    TKeyWordType article_type = NULL;

    if (ws->HasGztArticle()) {
        const TGztArticle& gzt_article = ws->GetGztArticle();
        article_title = gzt_article.GetTitle();
        article_type = gzt_article.GetType();
        const NGzt::TMessage* lemma = gzt_article.GetLemmaInfo();
        if (lemma != NULL)
            art_grammems = gzt_article.GetLemmaOutputGrammems(*lemma);
    } else if (ws->HasAuxArticle()) {
        const article_t* pArt = GlobalDictsHolder->GetAuxArticle(ws->GetAuxArticleIndex());
        art_grammems = pArt->get_new_pos();
        article_title = pArt->get_title();
        article_type = pArt->get_kw_type();
    }

    THomonymGrammems newGram;
    if (!ws->GetGrammems().Empty()) {
        newGram = ws->GetGrammems();
        if (!newGram.HasForms() && wh.IsValid())
            newGram.SetPOS(m_Words[wh].Grammems.GetPOS());
    } else if (wh.IsValid() && HasToAddGrammemsFromMainWord(*ws))
        newGram = m_Words[wh].Grammems;
    MergeGrammems(newGram, art_grammems, newPos);

    THomonymPtr pNewHom;
    if (pNewWord->IsMultiWord() && (pNewWord->GetSourcePair().Size() != 1 || !wh.IsValid())) {
        newWH.m_HomNum = FindOrMakeMultiwordHomonym(*ws, *pNewWord, article_type, newGram, pNewHom);
        YASSERT(newWH.IsValid());
    }

    if (pNewHom.Get() == NULL) {
        if (!pNewWord->IsMultiWord()) {
            if (wh.IsValid())
                newWH = wh;
            else {
                // just take the first homonym
                newWH.m_bOriginalWord = true;
                newWH.m_WordNum = pNewWord->GetSourcePair().FirstWord();
                newWH.m_HomNum = pNewWord->IterHomonyms().GetID();
            }
        }
        YASSERT(newWH.IsValid());
        //часто бывает ситуация, когда мы вынуждены клонировать абсолютно одинаковые
        //омонимы, различающиеся только приписанными статьями из aux_dic,
        //в случае с geo_thesaurus.cxx это чревато порождением огромного количества омонимов
        //(боле 50 для "Петров"), тогда если статьи не отличаются друг от друга полем СОСТАВ
        //приписываемыми граммемами, ЧР и KWType, то мы омонимы не клонируем а дополнительные статьи
        //записываем в CHomonym::m_KWtype2Articles. Это происходит в CWord::PutArticleIndex.
        //если мы считаем, что найденные статьи для одного и того же омонима ничем не отличаются,
        //то главное слово для неотличающихся стаей у ws одно и то же и ему приписана
        //первая попавшаяся среди неразличимы статья
        //например статьи "_петрова_2" и "_петрова_3" для нас одинаковы (отличаются только ГЕО_ЧАСТЬ
        //а это неважно для парсера) и незачем плодить омонимы
        bool bCloneAnyway = (!newGram.Empty() && !(m_Words[newWH].Grammems == newGram)) ||
                            !GlobalDictsHolder->BuiltinKWTypes().IsGeo(article_type);

        if (ws->HasAuxArticle())
            newWH.m_HomNum = m_Words.GetWord(newWH).PutAuxArticle(newWH.m_HomNum, ws->GetAuxArticleIndex(), bCloneAnyway);
        else
            newWH.m_HomNum = m_Words.GetWord(newWH).PutGztArticle(newWH.m_HomNum, ws->GetGztArticle(), bCloneAnyway);
    }
    YASSERT(newWH.IsValid());

    AddFoundArticle(article_type, article_title, newWH, searchAreaWP);
    CHomonym& h = m_Words[newWH];
    h.SetSourceWordSequence(ws);
    if (!newGram.Empty())
        h.SetGrammems(newGram);

    if (takeOnwership) {
        if (!ws->HasLemmas())
            NormalizeMultiWordHomonym(pNewWord, &h);
        m_wordSequences.push_back(ws);
    }

    return newWH;
}