bool RequiresSpace(const Wtroka& w1, const Wtroka& w2) { #define SHIFT(i) (ULL(1)<<(i)) if(w1.length() == 1) { if (NUnicode::CharHasType(w1[0], SHIFT(Ps_START) | SHIFT(Ps_SINGLE_QUOTE) | SHIFT(Pi_SINGLE_QUOTE) | SHIFT(Ps_QUOTE) | SHIFT(Pi_QUOTE))) return false; } if(w2.length() == 1) { if (NUnicode::CharHasType(w2[0], SHIFT(Pe_END) | SHIFT(Po_TERMINAL) | SHIFT(Pe_SINGLE_QUOTE) | SHIFT(Pf_SINGLE_QUOTE) | SHIFT(Pe_QUOTE) | SHIFT(Pf_QUOTE))) return false; } #undef SHIFT return true; }
// проверяет, содержит ли ситуация 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; }