Пример #1
0
void CRusSentence::BuildDash(int iClauseNum, int iWrdAfter, bool bCopul)
{
	SClauseType type;
	CClause&  pClause = GetClause(iClauseNum);

	if (bCopul)
	{
		pClause.ChangeAllClauseTypesToOneType(SClauseType(COPUL_T, -1,-1));		

		return;
	}

	if ( m_Words[iWrdAfter].IsInOborot() )
			return;

	if (pClause.IsInTermin(iWrdAfter)) return;

	if (IsBetweenGraphematicalPairDescriptors(iWrdAfter)) return;

	int DashWordNo = iWrdAfter + 1;
	m_Words.insert(m_Words.begin() + DashWordNo, CreateDash(this));

	RecalculateIndicesAfterInsertingWord(DashWordNo);
	pClause.ChangeAllClauseTypesToOneType(SClauseType(DASH_T, DashWordNo, 0) );		
}
Пример #2
0
//  проверяет, что вершина клаузы iClauseNum1 и вершина iClauseNum2 согласовани  как личные глагольные формы 
bool CRusSentence::CheckCoordinarionBetweenClauseRoots(GrammemCompare CompareFunc, int iClauseNum1, int iClauseNum2 ) const
{
	
	const CClause& C1 = GetClause(iClauseNum1);
	const CClause& C2 = GetClause(iClauseNum2);


	for (int i = 0; i < C1.m_vectorTypes.size(); i++)
		for (int k = 0; k < C2.m_vectorTypes.size(); k++)
			if (		!C1.m_vectorTypes[i].m_Root.IsEmpty()
					&&	!C2.m_vectorTypes[k].m_Root.IsEmpty()
				)
			{
				const CSynHomonym& H1 = m_Words[C1.m_vectorTypes[i].m_Root.m_WordNo].m_Homonyms[C1.m_vectorTypes[i].m_Root.m_HomonymNo];
				const CSynHomonym& H2 = m_Words[C2.m_vectorTypes[k].m_Root.m_WordNo].m_Homonyms[C2.m_vectorTypes[k].m_Root.m_HomonymNo];
                if (GetOpt()->GetGramTab()->Gleiche(CompareFunc, H1.m_GramCodes.c_str(), H2.m_GramCodes.c_str()))
                    return true;
			};
	return false;

};
Пример #3
0
/*
 Эта функция вызывается только из RuleForEmptyClauses. Проверяет, может ли 
 клауза войти в левостоящую. Если не может, тогда возвращает истину.
*/
bool CRusSentence::HasStrictBorderLeft(int iClauseNum)
{
	CClause* pAbstClause = &GetClause(iClauseNum);

	if( HasStrictestLeftClauseBorder(iClauseNum) )
		return true;

	if( iClauseNum == 0)
		return true;

	if( pAbstClause->HasLeftStarter() )
		return true;

	return false;
}
Пример #4
0
bool CRusSentence::FindNounFromTheRightOfParticiple(const CClause* pClause, const CSynHomonym& Participle) const
{
	int iType = pClause->FindType(PARTICIPLE_T);
	assert ( -1 != iType );

	// начинаем идти от причастия вправо
	for(int WordNo = pClause->m_vectorTypes[iType].m_Root.m_WordNo + 1 ; WordNo <= pClause->m_iLastWord ; WordNo++ )
	{
		const CSynWord& pWord = m_Words[WordNo];

		// проверка на вложенную клаузу, нужно увеличить индекс WordNo на длину вложенной клаузы
		int iEncloseCl = GetMinClauseByFirstWord(WordNo);
		if ( iEncloseCl != -1 )
		{
			assert (GetClause(iEncloseCl).is_inside_of(*pClause));

			WordNo = GetClause(iEncloseCl).m_iLastWord;
			continue;
		}
		
		CSVI Dummy;
		if ( pClause->IsInThisGroup(WordNo, PREP_NOUN, Dummy) ) continue;

		for(int j = 0 ; j < pWord.m_Homonyms.size() ; j++ )
		{
			const CSynHomonym& Noun = pWord.m_Homonyms[j];

			if( !GetRusGramTab()->IsMorphNoun(Noun.m_iPoses) ) continue;

			if (CheckCoordinationOfNounAndParticiple(Participle, pClause, WordNo, j))
				return true;
		}
	}

	return false;
}
Пример #5
0
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);
}
Пример #6
0
bool CRusSentence::RuleForEmptyClauses(int iClauseNum)
{
	const CClause& Clause = GetClause(iClauseNum);
	int iWord = Clause.m_iFirstWord; 

	if( !IsGoodEmptyClause( &Clause ) ) return false;

	bool bStrictPrevClauseBorder = HasStrictBorderLeft(iClauseNum);	

	//берем тот фрагмент, который стоит справа от найденной цепочки	
	//  если в текущую клаузу была вложена другая клауза, которая заканчивается там же, где текущая клауза
	// тогда  не будем добавлять пустыху направо (неоднозначность границ ),
	int iNext = GetMaxClauseByFirstWord(m_Clauses[iClauseNum].m_iLastWord+1);
	CClause* pAbstClauseRight = NULL;
	if( iNext != -1 )
		pAbstClauseRight = &GetClause(iNext);
	bool bCanConnectRight =		pAbstClauseRight 
							&& 	CanBeMainClauseOfTheLeftGoodEmptyClause(pAbstClauseRight, bStrictPrevClauseBorder)
							&&  (GetMinClauseByLastWord(Clause.m_iLastWord) == iClauseNum)
							&& !HasStrictBorderLeft(iNext);

	//берем тот фрагмент, который стоит слева от найденной цепочки
	CClause* pAbstClauseLeft = NULL;
	int iPrev = GetMinClauseByLastWord(Clause.m_iFirstWord-1);
	if( iPrev != -1 ) 
		pAbstClauseLeft = &GetClause(iPrev);

	//  если предыщая клауза была вложена в другую клаузу, тогда  не будем добавлять пустыху налево,
	//  поскольку  пустыха  может войти обе клаузы (в меньшую и в большую"),
	//   например:
	//  "интервью, опубликованное в четверг, 12 апреля" // "12 апреля"  надо вкладывать в причастный  оборот
	//  "упал кран, который  нам подарили японцы, 12 апреля" // "12 апреля"  надо вкладывать в главную клаузу
	// мы имеем здесь  абсолютныю неоднозначноть
	bool bCanConnectLeft =		pAbstClauseLeft 
							&&  !pAbstClauseLeft->HasType(INP_T)
							&&  !Clause.HasLeftStarter()
							&&  !IsEnclosedClause(iPrev)
							&&  !HasStrictestLeftClauseBorder(iClauseNum);


	// соединение влево будем считать более приоритетным
	if(bCanConnectLeft)
	{
		/* если объединяется пустыха  с инфинитивом,
		   тогда  тип объединенной клаузы должен быть инфинитовом 
		   если объединяется пустыха  со сравном,
		   тогда  тип объединенной клаузы должен быть СРАВН 
		*/
		if  ( (    Clause.HasType(INFINITIVE_T) 
			       || Clause.HasType(COMPARATIVE_T) 
			      ) 
				&& pAbstClauseLeft->m_vectorTypes.empty() 
				&& 1 == pAbstClauseLeft->m_vectorTypes.size() 
			)
			UniteClauses(iPrev, iClauseNum, RightClauseParams);
		else
			UniteClauses(iPrev, iClauseNum, LeftClauseParams);			

		return true;	
	}

	if(bCanConnectRight) 
	{
		UniteClauses(iClauseNum, iNext, RightClauseParams);
		return  true;
	} 



	return false;
}
Пример #7
0
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;
}
Пример #8
0
void CRusSentence::TryToRebuildDashInClause()
{
	StringVector v_CopulList;
	InitCopulList(v_CopulList);

	for (int ClauseNo = 0; ClauseNo < GetClausesCount(); ClauseNo++)
	{
		CClause&  pClause = GetClause(ClauseNo);

		if (!pClause.m_vectorTypes.empty()) 
			continue;

		bool bHasDash = false;
		if ( pClause.m_iFirstWord != 0 )
			for ( int tt = pClause.m_iFirstWord; tt <= pClause.m_iLastWord; tt++ )
				if ( m_Words[tt].m_bDash  )
				{
					bHasDash = true;
					break;
				}

		if ( bHasDash ) continue;


		int j = pClause.m_iFirstWord;
		for (; j <= pClause.m_iLastWord; j++)
			if (	!m_Words[j].GetSynHomonym(0).IsLemma("”")
				&&	m_Words[j].GetHomonymByPOS(PREP) != -1 
				)
				 break;

		if ( j < pClause.m_iLastWord ) continue;

		vector<int> Noun_Nom, Adj_Nom, Eto, Noun_Gen, Copul_Words, Noun_NomSgPl;
		int Prep_U = -1;
		bool Vozrast = false;

		for (j = pClause.m_iFirstWord; j <= pClause.m_iLastWord; j++)
		{
			if ( m_Words[j].GetSynHomonym(0).IsLemma("Ё“ќ")	)
			{
				Eto.push_back(j);
				continue;
			}

			for (int ll = 0; ll < v_CopulList.size(); ll++)
				if ( m_Words[j].m_strWord ==  v_CopulList[ll].c_str() )
				{
					Copul_Words.push_back(j);
					continue;
				}

			if ( m_Words[j].GetHomonymsCount() > 1 && !isdigit((BYTE)m_Words[j].m_strWord[0]) ) continue;

			if ( m_Words[j].GetSynHomonym(0).IsLemma(" ќ“ќ–џ…") )
				continue;

			if (		HasNounInNom( m_Words[j]) 
                && 	!m_Words[j].HasDes(OFAM2) 
					)
			{
				Noun_Nom.push_back(j);
				continue;
			
			}

			if ( 	HasAdjInNom(m_Words[j]) && !m_Words[j].HasDes(OFAM2) )
			{
				Adj_Nom.push_back(j);
				continue;
			}

			if ( m_Words[j].GetSynHomonym(0).IsLemma("”") )
			{
				Prep_U = j;
				continue;
			}

			if ( HasNounInGen(m_Words[j]) )
				Noun_Gen.push_back(j);

			if ( HasNounInNomSgPl( m_Words[j] ) )
				Noun_NomSgPl.push_back(j);
			
			if (0 == Adj_Nom.size() && 0 == Noun_Nom.size()
				&& isdigit((BYTE)m_Words[j].m_strWord[0]) // ≈му 33.
				&& m_Words[j].m_strWord.find("-") == string::npos && j >= m_Words.size()-2 
				&& !m_Words[m_Words.size()-1].m_Homonyms[0].m_bMonth && !m_Words[m_Words.size()-2].m_Homonyms[0].m_bMonth) 
			{
				Vozrast = true;
				Adj_Nom.push_back(j);
				continue;
			}
		}
		
		if (0 == Noun_Nom.size() && 0 == Eto.size() && 
			0 == Adj_Nom.size() && -1 == Prep_U)
			continue;
		if ( Vozrast && 0 < Noun_Nom.size() && m_Words[Noun_Nom[0]].m_strUpperWord == "√ќƒ" && 0 == Eto.size() && 1 == Adj_Nom.size() && -1 == Prep_U) //ему 21 год
			Noun_Nom.clear();

		if (0 == Noun_Nom.size() && 0 == Eto.size() && 1 == Adj_Nom.size() && -1 == Prep_U) // √лаза красивые.
			for (j = pClause.m_iFirstWord; j <= pClause.m_iLastWord; j++)
			{
				m_Words[j].SetHomonymsDel(true);
				for (int i = 0; i < m_Words[j].m_Homonyms.size() && 0 == Noun_Nom.size(); i++) 
				{
					if (  m_Words[j].m_Homonyms[i].IsSynNoun() ) 
					{
						if (  (m_Words[j].m_Homonyms[i].HasGrammem(rNominativ)
							&& (m_Words[j].m_Homonyms[i].m_iGrammems & rAllNumbers & m_Words[Adj_Nom[0]].GetGrammems())
							&& (m_Words[j].m_Homonyms[i].HasGrammem(rPlural) // согласуем род если ед.ч.
								|| (m_Words[j].m_Homonyms[i].m_iGrammems & rAllGenders & m_Words[Adj_Nom[0]].GetGrammems()))) 
								|| (Vozrast && m_Words[j].m_Homonyms[i].HasGrammem(rDativ) )) // ≈му 33.
						{
							m_Words[j].m_Homonyms[i].m_bDelete = false;
							Noun_Nom.push_back(j);
						}
					}
				}
				if (Noun_Nom.size() > 0 && find(Noun_Nom.begin(), Noun_Nom.end(), j) != Noun_Nom.end())
					m_Words[j].DeleteMarkedHomonymsBeforeClauses();
				else m_Words[j].SetHomonymsDel(false);
			}
		else Vozrast = false;

		if (Noun_Nom.size() > 1)
		{
			BYTE up_let = m_Words[Noun_Nom[1]].m_strWord[0];
			if (!is_russian_upper(up_let))
			{
				int k = 0;
				for (; k < Copul_Words.size(); k++)
					if (Copul_Words[k] > Noun_Nom[0] && Copul_Words[k] < Noun_Nom[1])
					{
						BuildDash(ClauseNo, -1, true);
						break;
					}

				if ( k == Copul_Words.size())
					BuildDash(ClauseNo, Noun_Nom[0]);
			}

			continue;
		}

		if ( Noun_Nom.size() > 0 && Eto.size() > 0 )
		{
			QWORD tormoz = _QM(rNeutrum) |  _QM(rSingular) |  _QM(rNominativ); 
			for (int k = 0; k < Eto.size() && k < Noun_Nom.size(); k++)
				//  без "тормоза" во фразе "это облако" восстановитс¤ тире
				if	(!m_Words[Noun_Nom[k]].GetSynHomonym(0).HasSetOfGrammemsExact(tormoz) )
					if (Noun_Nom[k] > Eto[k])
					{
						BuildDash(ClauseNo, Eto[k]);
						continue;
					}
		}		

		bool bPersCl, bEncCl;
		bPersCl = bEncCl = false;

		int cc = ClauseNo-1;
		for (; ClauseNo > 1 && cc >= 0; cc--)
		{
			CClause&  pClauseBefore = GetClause(cc);
		
			if (	pClauseBefore.HasType(VERB_PERS_T) 
					&& pClauseBefore.HasLeftStarter() 
				)
			{
					bEncCl = true;
					continue;
			}

			if ( pClauseBefore.HasType(PARTICIPLE_T) || pClauseBefore.HasType(ADVERB_PARTICIPLE_T) )
			{
					bEncCl = true;
					continue;
			}

			if ( pClauseBefore.HasType(DASH_T) )
				break;

			if (		(		!pClauseBefore.HasType(INFINITIVE_T) 
							&&  !pClauseBefore.m_vectorTypes.empty()
						)
					||  !(pClauseBefore.m_vectorTypes.size() == 1) 
				)
			{
				if (bEncCl)
					bPersCl = true;

				break;
			}

		}

		if (bPersCl) continue;

		bPersCl = bEncCl = false;

		for (cc = ClauseNo+1; ClauseNo < GetClausesCount()-2 && cc < GetClausesCount(); cc++)
		{
			CClause&  pClauseAfter = GetClause(cc);
		
			if (	pClauseAfter.HasType(VERB_PERS_T) 
				&&	pClauseAfter.HasLeftStarter() 
				)
			{
					bEncCl = true;
					continue;
			}

			if ( pClauseAfter.HasType(PARTICIPLE_T) || pClauseAfter.HasType(ADVERB_PARTICIPLE_T) )
			{
					bEncCl = true;
					continue;
			}

			if ( pClauseAfter.HasType(DASH_T) )
				break;

			if (	(			!pClauseAfter.HasType(INFINITIVE_T) 
						&& 		!pClauseAfter.m_vectorTypes.empty()
					) 
				||  !(pClauseAfter.m_vectorTypes.size() == 1) 
				)
			{
				if (bEncCl)
					bPersCl = true;

				break;
			}

		}
		
		if (bPersCl) continue;

		if ( Noun_Nom.size() > 0 && Adj_Nom.size() > 0 )
		{
			for (int k = 0; k < Noun_Nom.size() && k < Adj_Nom.size(); k++)
				if (      Noun_Nom[k] < Adj_Nom[k] 
                     &&  (pClause.m_iLastWord == Adj_Nom[k] || !HasGenderNumberCaseNP(m_Words[Adj_Nom[k]], m_Words[Adj_Nom[k]+1]) 
					 ||  Vozrast) //≈му 33 года
                   )
					 {
						if(Vozrast) 
							for (int h = 0; h < m_Words[Adj_Nom[k]].GetHomonymsCount(); h++)
								if(m_Words[Adj_Nom[k]].GetHomonym(h)->HasPos(NUMERAL))
									m_Words[Adj_Nom[k]].GetHomonym(h)->ModifyGrammems( _QM(rPlural) | _QM(rNominativ) | _QM(rAccusativ));
								else m_Words[Adj_Nom[k]].EraseHomonym(h);
			
						BuildDash(ClauseNo, Noun_Nom[k]);
						
					 }

			continue;
		}		
		
		if (-1 != Prep_U && Noun_Gen.size() > 0 && ( Noun_Nom.size() > 0 || Noun_NomSgPl.size() > 0 ) )
		{		
			for (int m = 0; m < Noun_Gen.size(); m++)
				if (Prep_U < Noun_Gen[m])
				{
					Prep_U = Noun_Gen[m];
					break;
				}
			if ( Noun_Nom.size() > 0 )
			{
				if ( Prep_U > Noun_Nom[0] )
						BuildDash(ClauseNo, Noun_Nom[0]);
				else
						BuildDash(ClauseNo, Prep_U);
				continue;
			}

			int iNomSgPl = -1;
			for ( int tt = 0; tt < Noun_NomSgPl.size(); tt++ )
				if ( Prep_U != Noun_NomSgPl[tt] )
				{
					iNomSgPl = Noun_NomSgPl[tt];
					break;
				}

			if ( -1 != iNomSgPl )
				if ( Prep_U > iNomSgPl )
						BuildDash(ClauseNo, iNomSgPl);
				else
						BuildDash(ClauseNo, Prep_U);
		}

	}
	
}