bool CSentence::GetWSLemmaString(Wtroka& sLemmas, const CWordSequence& ws, bool bLem) const { sLemmas = ws.GetCapitalizedLemma(); if (bLem) return !sLemmas.empty(); if (sLemmas.empty()) for (int j = ws.FirstWord(); j <= ws.LastWord(); j++) { if (!sLemmas.empty()) sLemmas += ' '; sLemmas += getWord(j)->GetOriginalText(); } static const Wtroka trim_chars = CharToWide(" \"\'"); TWtringBuf res = sLemmas; while (!res.empty() && trim_chars.find(res[0]) != TWtringBuf::npos) res.Skip(1); while (!res.empty() && trim_chars.find(res.back()) != TWtringBuf::npos) res.Chop(1); if (sLemmas.size() != res.size()) sLemmas = ::ToWtring(res); return true; }
void CQuotesFinder::CreateTextField(const Stroka& TextFieldName, CSentence* pSent, const SWordHomonymNum& WH, CFactFields& factFields, const Wtroka& Postfix) { CNormalization InterpNorm(pSent->m_Words); const CHomonym& h = pSent->m_Words[WH]; const CFioWordSequence* pFioWS = dynamic_cast<const CFioWordSequence*>(h.GetSourceWordSequence()); if (pFioWS != NULL) { CFioWS newFioWS(*pFioWS); newFioWS.SetMainWord(WH); newFioWS.AddLemma(SWordSequenceLemma (InterpNorm.GetArtificialLemma(WH))); CTextWS newTextWS; newTextWS.SetPair(*pFioWS); newTextWS.SetMainWord(WH); newTextWS.ResetLemmas(newFioWS.GetLemmas(), true); if (!Postfix.empty()) newTextWS.AddLemma(SWordSequenceLemma(Postfix)); factFields.AddValue(TextFieldName, newTextWS); } else { const CFactsWS* pFactWS = dynamic_cast<const CFactsWS*>(h.GetSourceWordSequence()); if (pFactWS) { CTextWS newTextWS; newTextWS.SetPair(*pFactWS); newTextWS.SetMainWord(WH); newTextWS.ResetLemmas(pFactWS->GetLemmas(), true); if (!Postfix.empty()) newTextWS.AddLemma(SWordSequenceLemma(Postfix)); factFields.AddValue(TextFieldName, newTextWS); } else { const CTextWS* pTextWS = dynamic_cast<const CTextWS*>(h.GetSourceWordSequence()); if (pTextWS) { CTextWS newTextWS = *pTextWS; if (!Postfix.empty()) newTextWS.AddLemma(SWordSequenceLemma(Postfix)); factFields.AddValue(TextFieldName, newTextWS); } else { if (h.GetSourceWordSequence() == 0 || h.GetSourceWordSequence()->Size() == 1) { CTextWS newTextWS; newTextWS.SetPair(pSent->m_Words.GetWord(WH).GetSourcePair()); newTextWS.SetMainWord(WH); newTextWS.AddLemma(SWordSequenceLemma(h.GetLemma())); if (!Postfix.empty()) newTextWS.AddLemma(SWordSequenceLemma(Postfix)); factFields.AddValue(TextFieldName, newTextWS); } } } } }
void ToFirstUpper(Wtroka& str) { if (!str.empty() && ::IsLower(str[0])) *(str.begin()) = static_cast<wchar16>(::ToUpper(str[0])); // TODO: this does not work properly for surrogate pairs (UTF-16) }
void SArtPointer::PutStrType(const Wtroka& s) { if (s.empty()) return; m_strArt = s; m_KWType = NULL; }
Wtroka CHomonym::GetLemma() const { if (m_pSourceWordSequence && (m_pSourceWordSequence->Size() > 1)) { Wtroka s = m_pSourceWordSequence->GetLemma(); if (!s.empty()) return s; } return CHomonymBase::GetLemma(); }
bool CQuotesFinder::CreateQuoteValue(const Wtroka& quoteStr, CFactFields& factFields) const { DECLARE_STATIC_RUS_WORD(kChto, "что "); DECLARE_STATIC_RUS_WORD(kChtoby, "чтобы "); Wtroka qstr = quoteStr; CTextWS QuoteWS; if (qstr.has_prefix(kChto)) qstr.erase(0,4); if (qstr.has_prefix(kChtoby)) qstr.erase(0,6); if (qstr.empty()) return false; qstr = StripString(qstr); if (qstr.size() > 1 && qstr[0] =='"' && qstr.back() =='"') qstr = qstr.substr(1, qstr.size() - 2); qstr = StripString(qstr); QuoteWS.AddLemma(SWordSequenceLemma(qstr)); QuoteWS.SetArtificialPair(CWordsPair(0,0)); factFields.AddValue(CFactFields::QuoteValue, QuoteWS); return true; }
// ищет закрывающую кавычку в текущем или последующем предложениях, // добавляет все слова до закрывающей кавычки к ResultToAdd // игнорируем внутренние кавычки bool CQuotesFinder::FindCloseQuoteInNextSentences(int StartSentNo, int StartWordForFirstSentence, Wtroka& ResultToAdd, yvector<SFactAddress>& FioInQuotes, SLeadInfo& LeadInfo) { Wtroka Add; yvector<SFactAddress> AddFioInQuotes; int Depth = 1; for (int SentNo=StartSentNo; (SentNo-StartSentNo<=2)&& (SentNo< (int)m_vecSentence.size()); SentNo++) { CSentenceRusProcessor* pSent = GetSentPrc(SentNo); yset<int> QuoteWords; int k=0; if (SentNo == StartSentNo) k = StartWordForFirstSentence; for (; k < (int)pSent->getWordsCount(); k++) { const CWord& w = *pSent->getWordRus(k); Add += w.GetOriginalText() + ' '; QuoteWords.insert(k); bool bHasCloseQuote = false; if (w.HasOpenQuote()) { if (ispunct(w.GetText()[0])) { Depth--; // одиночную кавычку знака препинания считаем закр. кавычкой (кто-то по ошибке поставил пробел) bHasCloseQuote = true;; } else Depth++; } if (w.HasCloseQuote()) { Depth--; if ((Depth == 1) // Закрывающая кавычка в конце предложения закрывает все открытые кавычки. && ((k+1 == (int)pSent->getWordsCount()) || ((k+2 == (int)pSent->getWordsCount()) && pSent->getWordRus(k+1)->IsPunct() ) ) ) { Depth = 0; } bHasCloseQuote = true; } if (w.GetText() == Wtroka::FromAscii("\"")) { if (k+1 == (int)pSent->getWordsCount() || pSent->getWordRus(k+1)->IsPunct()) { bHasCloseQuote = true; Depth--; } } if (bHasCloseQuote && Depth == 0) { if (!Add.empty() && Add[0] == '-') { const wchar16* beg = Add.begin() + 1; StripRangeBegin(beg, Add.end()); Add.assign(beg, Add.end() - beg); } if (ResultToAdd.back() == ',' && Add.size() > 0 && NStr::IsLangAlpha(Add[0], TMorph::GetMainLanguage()) && ::IsUpper(Add[0])) { ResultToAdd.erase(ResultToAdd.size() - 1); ResultToAdd += CharToWide(". "); } ResultToAdd += Add; AddFios(SentNo, QuoteWords, AddFioInQuotes); FioInQuotes.insert(FioInQuotes.end(), AddFioInQuotes.begin(), AddFioInQuotes.end()); LeadInfo.m_iLastSent = SentNo; return true; } } AddFios(SentNo, QuoteWords, AddFioInQuotes); } return false; }
// проверяет, содержит ли ситуация 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; }