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); }
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; }