bool CRusSentence::RuleForSubClauseWithCoordiantion(int iClauseNum) { const CClause* pAbstClause = &GetClause(iClauseNum); int iWord = pAbstClause->m_iFirstWord; if( pAbstClause->HasType(INP_T) || (pAbstClause->m_vectorTypes.size() == 0) ) return false; // берем следующую клаузу, которая должна быть с сочинительным союзом int iNext = GetMaxClauseByFirstWord(m_Clauses[iClauseNum].m_iLastWord+1); if(iNext == -1) return false; const CClause* pAbstClause1 = &GetClause(iNext); int type = pAbstClause1->FindCommonType(*pAbstClause); switch (type) { case INP_T : case -1 : return false; case PARTICIPLE_T: if (!CheckCoordinarionBetweenClauseRoots(GenderNumberCaseRussian, iClauseNum, iNext)) return false; break; case ADVERB_PARTICIPLE_T: break;// do noting default: if ( ClauseHasSubjPredik(GetClause(iNext)) // если вторая клаузы имеет подлежащее, тогда согласование искать не надо || !CheckCoordinarionBetweenClauseRoots(FiniteFormCoordRussian, iClauseNum, iNext) ) // проверка на неоднозначность границы if(GetMinClauseByLastWord(m_Clauses[iClauseNum].m_iLastWord) != GetMaxClauseByLastWord(m_Clauses[iClauseNum].m_iLastWord)) return false; /* если во вставляемой клаузе вершина омонимична, то мы должны делать следующее: 1. Либо удалить все непрeдикатные омонимы, оставив только прeдикаты, поскольку пустыха не может быть вложена; 2. Либо не обрабатывать эти случаи совсем, поскольку позже с непредикатными омонимами может что-нибудь хорошее произойти Мы предпочитаем второе решение, хотя это фактически использование старого определения пустыхи, что не очень идеологично. Когда-нибудь нужно будет поменять. Сокирко 31.10.02 */ if (!pAbstClause1->HasUnambiguousStrongRootWithoutWeakHomonyms()) return false; break; } if( pAbstClause1->size() < 2 ) return false; int iFirstWord = pAbstClause1->m_iFirstWord; bool bCoordConj = ( (GetWords()[iFirstWord].m_strWord[0] == ',') && m_Words[iFirstWord+1].m_bSimilarConj ) || m_Words[iFirstWord].m_bSimilarConj; if (!bCoordConj) return false; return EncloseClauseAsWord(iNext, iClauseNum); }
bool CRusSentence::RuleForParticiples(int iClauseNum) { CClause* pAbstClause = &GetClause(iClauseNum); int iWord = pAbstClause->m_iFirstWord; if ( IsEnclosedClause (iClauseNum) ) return false; if ( pAbstClause->HasUnambiguousStrongRootWithoutWeakHomonyms()) return false; int iParticipleType; if( (iParticipleType = pAbstClause->FindType(PARTICIPLE_T)) == -1 ) return false; assert(!pAbstClause->m_vectorTypes[iParticipleType].m_Root.IsEmpty()); CSynWord& pParticiple = m_Words[pAbstClause->m_vectorTypes[iParticipleType].m_Root.m_WordNo]; int iPart = pParticiple.GetHomonymByPOS(PARTICIPLE); if( iPart == -1 ) return false; //пытаемся найти слева int iPrev = FindNounFromTheLeftOfParticiple(pAbstClause, pParticiple.GetSynHomonym(iPart)); //пытаемся найти слева подходящее сущ.(тогда причастие после определяемого слова) if ( ( m_Words[iWord].m_SubordinateConjNo == -1 ) && ( (pAbstClause->m_iFirstWord != pAbstClause->m_iLastWord ) || ( (iWord+1<m_Words.size()) && (m_Words[iWord+1].m_SubordinateConjNo != -1 ) ) ) && (iPrev != -1) && ( pAbstClause->m_iLastWord+1 == m_Words.size() // проверка правой границы (должен быть знак препинания) || m_Words[pAbstClause->m_iLastWord+1].HasDes(OPun) ) ) { /* Поскольку мы собираемся вкладывать клаузу, нам приходится удалять все вершины клаузы, кроме найденного причастия и все омонимы причастия */ // уничтожаем другие вершины клаузы int k = 0; for( ; k < pAbstClause->m_vectorTypes.size() ; k++) { if(iParticipleType == k) continue; if(k < iParticipleType) iParticipleType--; int WordNo = pAbstClause->m_vectorTypes[k].m_Root.m_WordNo; // не будем удалять омоним, если он единственный у слова if (pAbstClause->GetWords()[WordNo].GetHomonymsCount() > 1) pAbstClause->DeleteHomonym(pAbstClause->m_vectorTypes[k].m_Root.m_WordNo, pAbstClause->m_vectorTypes[k].m_Root.m_HomonymNo); else pAbstClause->DeleteClauseType( k ); k--; } // заново надо найти омоними причастия, поскольку мы в предыдущем цикле удалили некоторые омонимы iPart = pParticiple.GetHomonymByPOS(PARTICIPLE); int PartWordNo = pAbstClause->m_vectorTypes[iParticipleType].m_Root.m_WordNo; // уничтожаем омонимы причастия (прилагательное или существительное), for(k = 0 ; k < pParticiple.GetHomonymsCount() ; k++) { if(iPart == k) continue; if(k < iPart) iPart--; pAbstClause->DeleteHomonym(PartWordNo, k); k--; } return EncloseClauseAsWord(iClauseNum, iPrev); } else // пытаемся найти справа (причастие не отделено запятой) if( FindNounFromTheRightOfParticiple(pAbstClause, pParticiple.GetSynHomonym(iPart) ) ) { // тогда нужно удалить клаузный вариант причастия, а если вариант только один, тогда // нужно его отконвертировать в пустыху if(pAbstClause->m_vectorTypes.size() == 1) { assert (pAbstClause->m_vectorTypes[0].m_Type == PARTICIPLE_T); pAbstClause->ChangeAllClauseTypesToOneType( SClauseType(UnknownSyntaxElement,-1,-1) ); } else { assert( iParticipleType >= 0); pAbstClause->DeleteClauseType( iParticipleType ); } } return false; }