void CMultiWordCreator::GetFoundWordsInPeriod(const SArtPointer& artP, yvector<SWordHomonymNum>& foundWords, const CWordsPair& wp) const { foundWords.clear(); //сначала пытаемся найти среди KwType, которые уже искались на всем предложении, те, которые //входят в наш отрезок if (artP.HasKWType()) { ymap<TKeyWordType, yvector<SWordHomonymNum> >::const_iterator it = m_KW2Words.find(artP.GetKWType()); if (it != m_KW2Words.end()) { const yvector<SWordHomonymNum>& whs = it->second; for (size_t i = 0; i < whs.size(); i++) { CWord& w = m_Words.GetWord(whs[i]); if (wp.Includes(w.GetSourcePair())) foundWords.push_back(whs[i]); } } } if (!foundWords.empty()) return; //пытаемся найти среди StrType, которые уже искались на всем предложении, те, которые //входят в наш отрезок if (artP.HasStrType()) { ymap<Wtroka, yvector<SWordHomonymNum> >::const_iterator it = m_Title2Words.find(artP.GetStrType()); if (it != m_Title2Words.end()) { const yvector<SWordHomonymNum>& whs = it->second; for (size_t i = 0; i < whs.size(); ++i) { CWord& w = m_Words.GetWord(whs[i]); if (wp.Includes(w.GetSourcePair())) foundWords.push_back(whs[i]); } } } if (!foundWords.empty()) return; //теперь проходим по запомненным отрезкам, для которых хранятся все найденные MultiWords ymap<CWordsPair, yvector<SWordHomonymNum> >::const_iterator it = m_FoundWordsByPeriod.find(wp); if (it != m_FoundWordsByPeriod.end()) { const yvector<SWordHomonymNum>& whs = it->second; for (size_t i = 0; i < whs.size(); i++) { const CHomonym& h = m_Words[whs[i]]; if (h.HasArticle(artP, KW_DICT)) foundWords.push_back(whs[i]); } } }
//выдает абсолютный адрес найденной ситуации цитирования CWordsPair CQuotesFinder::GetWordIndexOfQuoteSituation(const SValenciesValues& VerbCommunic, int SentNo) const { CWordsPair PairToSearch; PairToSearch.SetPair(-1,-1); const CSentenceRusProcessor* pSentPrc = GetSentPrc(SentNo); if (VerbCommunic.m_NodeWH.IsValid()) { // если валидна вершина,берем координаты веришины PairToSearch = pSentPrc->m_Words.GetWord(VerbCommunic.m_NodeWH).GetSourcePair(); } else { // иначе берем координаты первой валентности if (VerbCommunic.m_values.empty() || !VerbCommunic.m_values[0].m_Value.IsValid()) return CWordsPair(); PairToSearch = pSentPrc->m_Words.GetWord(VerbCommunic.m_values[0].m_Value).GetSourcePair(); }; return PairToSearch; };
// он сказал : "У меня было право - я исполнял обязанности премьера" . // он сказал : " У меня было право - я исполнял обязанности премьера" . bool CQuotesFinder::TryDirectSpeechWithColon(const SValenciesValues& VerbCommunic, int SentNo) { if (!VerbCommunic.m_NodeWH.IsValid()) return false; CSentenceRusProcessor* pSentPrc = GetSentPrc(SentNo); const CWordsPair PairToSearch = GetWordIndexOfQuoteSituation(VerbCommunic, SentNo); if (PairToSearch.FirstWord() == -1) return false; const_clause_it min_it = GetSentPrc(SentNo)->GetClauseStructureOrBuilt().GetMinimalClauseThatContains(PairToSearch); const CClauseVariant& ClauseVariant = pSentPrc->GetClauseStructureOrBuilt(); if (min_it == ClauseVariant.GetEndClause()) return false; const CClause* pEnclosedClause = ClauseVariant.GetIncludedClauseR(min_it); CWordsPair QuoteValuePair; if (pEnclosedClause && pEnclosedClause->FirstWord() != 0) { const Wtroka& WordStr = pSentPrc->getWordRus(pEnclosedClause->FirstWord() - 1)->GetText(); if (WordStr != COLON && (WordStr != Wtroka::FromAscii("\"") || pEnclosedClause->FirstWord() < 2 || pSentPrc->getWordRus(pEnclosedClause->FirstWord() - 2)->GetText() != COLON)) return false; QuoteValuePair = *pEnclosedClause; } else { int LastWord = (**min_it).LastWord(); const Wtroka& WordStr = pSentPrc->getWordRus(LastWord)->GetText(); if (WordStr != COLON && (WordStr != Wtroka::FromAscii("\"") || LastWord < 1 || pSentPrc->getWordRus(LastWord - 1)->GetText() != COLON)) return false; if (LastWord + 1 == (int)pSentPrc->getWordsCount()) return false; QuoteValuePair = CWordsPair(LastWord+1, (int)pSentPrc->getWordsCount() - 1); } yvector<SFactAddress> FioInQuotes; AddFiosFromPeriod(SentNo, QuoteValuePair, FioInQuotes); return AddQuoteFact(VerbCommunic, pSentPrc, pSentPrc->ToString(QuoteValuePair), FioInQuotes, SLeadInfo()); }
void CMultiWordCreator::AddFoundArticle(TKeyWordType article_type, const Wtroka& article_title, const SWordHomonymNum& word, const CWordsPair& searchAreaWP) { if (searchAreaWP.IsValid()) { m_FoundWordsByPeriod[searchAreaWP].push_back(word); return; } //m_Words[word].Lock(); if (article_type != NULL) m_KW2Words[article_type].push_back(word); m_Title2Words[article_title].push_back(word); };
void CQuotesFinder::AddFiosFromPeriod(int SentNo, const CWordsPair& Pair, yvector<SFactAddress>& FioInQuotes) { CSentenceRusProcessor* pSentPrc = GetSentPrc(SentNo); yvector<SWordHomonymNum>* fioWHs = pSentPrc->GetMultiWordCreator().GetFoundWords(GlobalDictsHolder->BuiltinKWTypes().Fio, KW_DICT); if (fioWHs) for (size_t i=0; i < fioWHs->size(); i++) { const CHomonym& pHom = pSentPrc->m_Words[(*fioWHs)[i] ]; if (Pair.Includes(*pHom.GetSourceWordSequence())) { SFactAddress A; A.m_HomNum = (*fioWHs)[i].m_HomNum; A.m_WordNum = (*fioWHs)[i].m_WordNum; A.m_bOriginalWord = (*fioWHs)[i].m_bOriginalWord; A.m_iSentNum = SentNo; FioInQuotes.push_back(A); } } }
// обычно функция возвращает clause->ToString(), // если в клаузе есть открывающая кавычка, а нет закрывающей, тогда функция добавляет к результату // все слова до закрывающей кавычки Wtroka CQuotesFinder::FindRightQuoteIfHas(const CWordsPair& PeriodToPrint, int SentNo, const CWordsPair& GroupToExclude, yvector<SFactAddress>& FioInQuotes) { FioInQuotes.clear(); CSentenceRusProcessor* pSentPrc = GetSentPrc(SentNo); yset<int> QuoteWords; Wtroka ClauseStr; static const Wtroka COMMA = Wtroka::FromAscii(","); for (int i = PeriodToPrint.FirstWord(); i <= PeriodToPrint.LastWord(); i++) { const CWord& w = pSentPrc->m_Words.GetOriginalWord(i); if (!GroupToExclude.Contains(i) && !(GroupToExclude.Contains(i - 1) && w.GetText() == COMMA) && !(GroupToExclude.Contains(i + 1) && w.GetText() == COMMA)) { ClauseStr += w.GetOriginalText() + ' '; QuoteWords.insert(i); } } size_t index = ClauseStr.find('"'); if (index != Wtroka::npos && ClauseStr.rfind('"') == index) { yset<int> AddQuoteWords; Wtroka Add; // если только одна кавычка, то пойдем искать вторую кавычку int i; for (i = PeriodToPrint.LastWord()+1; i < (int)pSentPrc->getWordsCount(); i++) { const CWord& w = pSentPrc->m_Words.GetOriginalWord(i); if (!GroupToExclude.Contains(i)) { Add += w.GetOriginalText() + ' '; AddQuoteWords.insert(i); } if (w.HasCloseQuote()) break; } if (i != (int)pSentPrc->getWordsCount()) { ClauseStr += ' '; ClauseStr += Add; QuoteWords.insert(AddQuoteWords.begin(), AddQuoteWords.end()); } } AddFios(SentNo, QuoteWords, FioInQuotes); return ClauseStr; };
// проверяет, содержит ли ситуация VerbCommunic прямую речь в качестве актанта-клаузы, примеры: // "Я счастлив", - сказал Петя. // "Я счастлив. Я очень счастлив", - сказал Петя. // "Я счаcтлив, - сказал Петя. - Я очень счастлив!" bool CQuotesFinder::TryDirectSpeechWithDashes(const SValenciesValues& VerbCommunic, int SentNo) { if (!VerbCommunic.m_NodeWH.IsValid()) return false; CSentenceRusProcessor* pSentPrc = GetSentPrc(SentNo); const CWordsPair PairToSearch = GetWordIndexOfQuoteSituation(VerbCommunic, SentNo); if (PairToSearch.FirstWord() == -1) return false; int EndDirectSpeech = PairToSearch.FirstWord(); { bool bFound = false; // ищем тире на расстоянии 5 слов от глагола for (int i=EndDirectSpeech-1; i>0 && EndDirectSpeech-i<5; i--) { if (pSentPrc->getWordRus(i)->IsDash()) { EndDirectSpeech = i; bFound = true; break; } } if (!bFound) return false; } EndDirectSpeech--; if (EndDirectSpeech < 0 ||!pSentPrc->getWordRus(EndDirectSpeech)->IsComma()) return false; EndDirectSpeech--; bool bHasCloseQuote = true; if (EndDirectSpeech < 0 ||!pSentPrc->getWordRus(EndDirectSpeech)->HasCloseQuote()) { bHasCloseQuote = false; EndDirectSpeech ++; } yvector<SFactAddress> FioInQuotes; Wtroka QuoteStr; SLeadInfo LeadInfo; LeadInfo.m_iFirstSent = SentNo; LeadInfo.m_iLastSent = SentNo; if (FindOpenQuoteInThisSentence(SentNo, EndDirectSpeech, QuoteStr, FioInQuotes)) { } else { // ищем открывающую кавычку в другом предложении int StartSentNo = FindBeginQuote(SentNo); if (StartSentNo == -1) return false; LeadInfo.m_iFirstSent = StartSentNo; for (int i=StartSentNo; i+1<=SentNo; i++) { CSentenceRusProcessor* pSnt = GetSentPrc(i); QuoteStr += pSnt->ToString(); QuoteStr += ' '; AddFiosFromPeriod(i, CWordsPair(0, (int)pSnt->getWordsCount() - 1),FioInQuotes); } LeadInfo.m_iLastSent = SentNo; CWordsPair p(0, EndDirectSpeech); QuoteStr += pSentPrc->ToString(p); AddFiosFromPeriod(SentNo, p, FioInQuotes); } if (!bHasCloseQuote) { // берем клаузу const_clause_it min_it = GetSentPrc(SentNo)->GetClauseStructureOrBuilt().GetMinimalClauseThatContains(PairToSearch); const CClauseVariant& ClauseVariant = pSentPrc->GetClauseStructureOrBuilt(); if (min_it == ClauseVariant.GetEndClause()) return false; // проверяем, что клауза с ситуацией в предложении последняя if ((**min_it).LastWord()+1 == (int)pSentPrc->getWordsCount()) { // ищет закрывающую кавычку в следующем предложении if (!FindCloseQuoteInNextSentences(SentNo+1, 0, QuoteStr, FioInQuotes, LeadInfo)) return false; } else if (!FindCloseQuoteInNextSentences(SentNo, (**min_it).LastWord(), QuoteStr, FioInQuotes, LeadInfo)) return false; } return AddQuoteFact(VerbCommunic, pSentPrc, QuoteStr, FioInQuotes, LeadInfo); }
// проверяет, содержит ли ситуация VerbCommunic косвенную речь в качестве актанта-клаузы. Примеры: // "Петров сказал, что мы уходим в Яндекс." // По словам Сергея Крапина , я уехал // Она призналась , что "придумали проект наружной рекламы , но притормозили его , не захотев оказаться" . bool CQuotesFinder::TryIndirectSpeech(const SValenciesValues& VerbCommunic, int SentNo) { CWordsPair PairToSearch = GetWordIndexOfQuoteSituation(VerbCommunic, SentNo); if (PairToSearch.FirstWord() == -1) return false; const_clause_it min_it = GetSentPrc(SentNo)->GetClauseStructureOrBuilt().GetMinimalClauseThatContains(PairToSearch); CSentenceRusProcessor* pSentPrc = GetSentPrc(SentNo); const CClauseVariant& ClauseVariant = pSentPrc->GetClauseStructureOrBuilt(); if (min_it == ClauseVariant.GetEndClause()) return false; // пропускаем непервые клаузы, которые заканчиваются на тире, поскольку, это может быть только прямая речь. if ((**min_it).FirstWord() != 0 && pSentPrc->getWordRus((**min_it).LastWord())->GetText() == Wtroka::FromAscii("-")) return false; // вычисляем союз по названию статьи, например, из "_глагол_со_чтобы" получаем "чтобы" Wtroka strValencySubConj; { DECLARE_STATIC_RUS_WORD(kChto, "что"); DECLARE_STATIC_RUS_WORD(kChtoby, "чтобы"); Wtroka t = VerbCommunic.m_pArt->get_title(); if (t.length() > 4 && t[t.length() - 4] == '_' && t.has_suffix(kChto)) strValencySubConj = kChto; else if (t.length() > 6 && t[t.length() - 6] == '_' && t.has_suffix(kChtoby)) strValencySubConj = kChtoby; } // если справа стоит клауза со "что" if (!strValencySubConj.empty()) { yvector<const CClause*> SubClauses; ClauseVariant.GetIncludedClauses(min_it, SubClauses); std::sort(SubClauses.begin(), SubClauses.end(), LessBySize); { // берем первую справа const_clause_it next_it; ClauseVariant.GetNeighbourClauseR(min_it, next_it); if (next_it != ClauseVariant.GetEndClause()) SubClauses.push_back(*next_it); } // берем вложенную клаузу справа (это лучший вариант) { const CClause* pSubClause = ClauseVariant.GetIncludedClauseR(min_it); if (pSubClause) SubClauses.push_back(pSubClause); } for (int i=SubClauses.size()-1; i >=0; i--) { const CClause* pSubClause = SubClauses[i]; if (pSubClause->FromRight(PairToSearch)) for (int ConjNo=0; ConjNo < pSubClause->GetConjsCount(); ConjNo++) { const CHomonym& Conj = pSubClause->GetConj(ConjNo); const article_t* piConjArt = GlobalDictsHolder->GetAuxArticle(Conj, CONJ_DICT); if (piConjArt->get_title().substr(0, strValencySubConj.length()) == strValencySubConj) { yvector<SFactAddress> FioInQuotes; Wtroka QuoteStr = FindRightQuoteIfHas(*pSubClause, SentNo, CWordsPair(), FioInQuotes); if (AddQuoteFact(VerbCommunic, pSentPrc, QuoteStr, FioInQuotes, SLeadInfo())) return true; } }; } } // если клауза является вводной DECLARE_STATIC_RUS_WORD(kPo_slovam_Ivanova, "по_словам_иванова"); DECLARE_STATIC_RUS_WORD(kKak, "как"); if ((VerbCommunic.m_pArt->get_title() == kPo_slovam_Ivanova && (*min_it)->HasType(Parenth)) || // или использована с союзом "как", например, "как рассказал Петров, мы уже ушли" (pSentPrc->getWordRus((*min_it)->FirstWord())->FindLemma(kKak) && ClauseVariant.GetIncludedClauseL(min_it) == 0)) { // если вводная калуза стоит на первом месте и в предложении нет других клауз, тогда берем // все предложение начиная от конца вводной клаузы до if ((**min_it).FirstWord() == 0) { yvector<SFactAddress> FioInQuotes; Wtroka QuoteStr = FindRightQuoteIfHas(CWordsPair((**min_it).LastWord(), pSentPrc->getWordsCount() - 1), SentNo, **min_it, FioInQuotes); if (AddQuoteFact(VerbCommunic, pSentPrc, QuoteStr, FioInQuotes, SLeadInfo())) return true; }; // берем главную клаузу const CClause* pMainClause = ClauseVariant.GetMainClause(min_it); if (!pMainClause) { const_clause_it next_it; ClauseVariant.GetNeighbourClauseR(min_it, next_it); if (next_it != ClauseVariant.GetEndClause()) pMainClause = *next_it; } if (pMainClause) { // печатаем главную клаузу без вложенной yvector<SFactAddress> FioInQuotes; Wtroka QuoteStr = FindRightQuoteIfHas(*pMainClause, SentNo, **min_it, FioInQuotes); if (AddQuoteFact(VerbCommunic, pSentPrc, QuoteStr,FioInQuotes, SLeadInfo())) return true; } } return false; }