Склонение по падежам
Добавлено: 27 май 2010, 21:38
Накидал интерфейс для склонения предложений, состоящих из существительных (в именительном падеже) и прилагательных. Искал что-то стандартное. Галактический интерфейс склонения фамилий не устроил, так что сел за велосипед. Функционал затачивался в основном под наименования отделов и ЦО, 90% предложений проходят (параметр stopAfterNoun = true). Можно использовать для наименований объектов ремонта и строительства (stopAfterNoun = false). Есть глюки с родами (например "двигатель" и "ночь", заканчиваются мягким знаком, окончания будут разные, но в программе это не учитывается). Может кому пригодится
Результат
Код: Выделить всё
// Файл StringUtils.vih
#ifndef __StringUtils_vih__
#define __StringUtils_vih__
#component "Utils"
// Падежи
const
csNominativeCase = 1; // Именительный падеж (Кто? Что?)
csGenitiveCase = 2; // Родительный падеж (Кого? Чего?)
csDativeCase = 3; // Дательный (Кому? Чему?)
csAccusativeCase = 4; // Винительный (Кого? Что?)
csInstrumentativeCase = 5; // Творительный (Кем? Чем?)
csPrepositionCase = 6; // Предложный (О ком? О чём?)
end;
// Части речи
const
csUnknownWord = 0; // Неопределенное
csNounWord = 1; // Существительное
csAdjectiveWord = 2; // Прилагательное
end;
// Тип данных -> слово и часть речи
public type tWordWithType = record
WordStr : string;
WordType : byte;
end;
public type StringArray = array [1..1] of string;
public objInterface IStringUtils;
public:
////////////////////////////////////////////////////////////////////////
// Склонение слов и предложений, сос`тоящих из существительных и прилагательных
// _case - падеж (константа)
// stopAfterNoun - прекратить склонение после того как наткнулись на существительное
////////////////////////////////////////////////////////////////////////
function ConvertWordToCase(str : string; _case : byte) : tWordWithType;
function ConvertStatementToCase(str : string; _case : byte; stopAfterNoun : boolean = false) : string;
end;
public vipInterface StringUtils implements IStringUtils;
#end
// Файл StringUtils.vip
#component "Utils"
interface StringUtils;
type tCaseParam = record
AdjEnd : array[1..6] of string;
NounEnd : array[1..7] of string;
end;
var _caseParams : array [1..6] of tCaseParam; // Параметры склонений
////////////////////////////////////////////////////////////////////////
// Склонение слов и предложений, состоящих из существительных и прилагательных
// _case - падеж (константа)
// onlyAdjective - склонять только прилагательные
////////////////////////////////////////////////////////////////////////
private function ConvertWordToCaseInternal(str : string; _case : byte; onlyAdjective : boolean) : tWordWithType;
{
result.WordStr := str;
result.WordType := csUnknownWord;
if (_case < csGenitiveCase or _case > csPrepositionCase)
exit;
var strLen : byte;
var cutLen : byte;
var ending : string;
var wordType : byte;
var caseParam : tCaseParam;
str := Trim(str);
strLen := Length(str);
if (str = '' or strLen < 3) // максимальная длина окончания 2 символа
exit;
caseParam := _caseParams[_case];
// 1-й уровень проверки - на прилагательное
wordType := csAdjectiveWord;
cutLen := 2;
ending := SubStr(str, Byte(strLen - 1), cutLen);
if (UpCase(str) = 'СТОЛОВАЯ') // Исключения
{
wordType := csNounWord;
}
case ending of
'ой': ending := caseParam.AdjEnd[1];
'ое': ending := caseParam.AdjEnd[2];
'ый': ending := caseParam.AdjEnd[3];
'ий': ending := caseParam.AdjEnd[4];
'ее': ending := caseParam.AdjEnd[5];
'ая': ending := caseParam.AdjEnd[6];
else { ending := ''; wordType := csUnknownWord; }
end;
//}
// 2 уровень проверки - на существительное
if (wordType = csUnknownWord and (not onlyAdjective))
{
wordType := csNounWord;
if (UpCase(str) = 'БЮРО') // Исключения
{
cutLen := 0;
ending := '';
}
else
{
cutLen := 1;
ending := SubStr(str, strLen, cutLen);
case ending of
'б', 'в', 'г', 'д', 'ж', 'з', 'к', 'л', 'м', 'н', 'п', 'р', 'с', 'т', 'ф', 'х', 'ц', 'ч', 'ш', 'щ':
{
ending := caseParam.NounEnd[1];
cutLen := 0;
}
'а': ending := caseParam.NounEnd[2];
'е': ending := caseParam.NounEnd[3];
'о': ending := caseParam.NounEnd[4];
'ы': ending := caseParam.NounEnd[5];
'я': ending := caseParam.NounEnd[6];
'ь': ending := caseParam.NounEnd[7]; // Здесь ошибка из-за рода: модель и двигатель
else { ending := ''; wordType := csUnknownWord; }
end;
}
}
if (wordType <> csUnknownWord)
{
result.WordStr := SubStr(str, 1, Byte(strLen - cutLen)) + ending;
result.WordType := wordType;
}
result := result;
}
////////////////////////////////////////////////////////////////////////
// Склонить слово
// Слово должно быть в именительном падеже и единственном числе
////////////////////////////////////////////////////////////////////////
public function IStringUtils.ConvertWordToCase(str : string; _case : byte) : tWordWithType;
{
result := ConvertWordToCaseInternal(str, _case, false);
}
public function IStringUtils.ConvertStatementToCase(str : string; _case : byte; stopAfterNoun : boolean = false) : string;
{
if (_case < csGenitiveCase or _case > csPrepositionCase)
{
result := str;
exit;
}
result := '';
var i : byte;
var strLen : word;
strLen := Length(str);
var curWordLen : byte;
curWordLen := 0;
var wasNoun : boolean; // Признак того, что нашлось существительное
wasNoun := false;
for (i := 1; i <= strLen; i++)
{
var curChar : char;
var needCut : boolean; // Признак того, что необходимо выделять слово для преобразования
var wasDelim : boolean;
var cutPos : byte;
curChar := str[i];
needCut := false;
if (curChar = ' ' or curChar = ',') // Проверка на разделитель слов в предложении
{
if (curWordLen > 0)
{
needCut := true;
cutPos := i - curWordLen;
wasDelim := true;
}
else result += curChar;
}
else
{
curWordLen++;
if (i = strLen) // Дошли до конца выражения
{
needCut := true;
cutPos := i - curWordLen + 1;
wasDelim := false;
}
}
if (needCut)
{
var wordWithType : tWordWithType;
wordWithType := ConvertWordToCaseInternal(SubStr(str, cutPos, curWordLen), _case, wasNoun);
result += wordWithType.WordStr + if(wasDelim, curChar, '');
curWordLen := 0;
if (wordWithType.WordType = csNounWord and i <> strLen)
{
wasNoun := true;
if (stopAfterNoun)
{
result += SubStr(str, i + 1, strLen - i);
break;
}
}
}
}
}
handleEvent
cmOnVipLoad:
{
/*
Окончания прилагательных
[1] 'ой' // ДеловОЙ
[2] 'ое' // КрасивОЕ
[3] 'ый' // КрасивЫЙ
[4] 'ий' // ТехническИЙ
[5] 'ее' // ОбщЕЕ
[6] 'ая' // СчастливАЯ
Окончания существительных
[1] 'б', 'в', 'г', 'д', 'ж', 'з', 'к', 'л', 'м', 'н', 'п', 'р', 'с', 'т', 'ф', 'х', 'ц', 'ч', 'ш', 'щ' // Отдел
[2] 'а' // РаботА
[3] 'е' // ПолЕ
[4] 'о' // ОкнО
[5] 'ы' // НасосЫ
[6] 'я' // НянЯ
[7] 'ь' // Модель, двигатель
*/
var caseParam : tCaseParam;
////////////////////////////////////////////////////////////////////////
// Именительный падеж (кто, что)
////////////////////////////////////////////////////////////////////////
ClearAdvRecord(caseParam);
_caseParams[1] := caseParam;
////////////////////////////////////////////////////////////////////////
// Родительный падеж (кого, чего)
////////////////////////////////////////////////////////////////////////
ClearAdvRecord(caseParam);
caseParam.AdjEnd[1] := 'ого';
caseParam.AdjEnd[2] := 'ого';
caseParam.AdjEnd[3] := 'ого';
caseParam.AdjEnd[4] := 'ого';
caseParam.AdjEnd[5] := 'его';
caseParam.AdjEnd[6] := 'ой';
caseParam.NounEnd[1] := 'а';
caseParam.NounEnd[2] := 'ы';
caseParam.NounEnd[3] := 'я';
caseParam.NounEnd[4] := 'а';
caseParam.NounEnd[5] := 'ов';
caseParam.NounEnd[6] := 'и';
caseParam.NounEnd[7] := 'и';
_caseParams[2] := caseParam;
////////////////////////////////////////////////////////////////////////
// Дательный падеж (кому, чему)
////////////////////////////////////////////////////////////////////////
ClearAdvRecord(caseParam);
caseParam.AdjEnd[1] := 'ому';
caseParam.AdjEnd[2] := 'ому';
caseParam.AdjEnd[3] := 'ому';
caseParam.AdjEnd[4] := 'ому';
caseParam.AdjEnd[5] := 'ему';
caseParam.AdjEnd[6] := 'ой';
caseParam.NounEnd[1] := 'у';
caseParam.NounEnd[2] := 'е';
caseParam.NounEnd[3] := 'ю';
caseParam.NounEnd[4] := 'у';
caseParam.NounEnd[5] := 'ам';
caseParam.NounEnd[6] := 'е';
caseParam.NounEnd[7] := 'и';
_caseParams[3] := caseParam;
////////////////////////////////////////////////////////////////////////
// Винительный падеж (кого, что)
////////////////////////////////////////////////////////////////////////
ClearAdvRecord(caseParam);
caseParam.AdjEnd[1] := 'ого';
caseParam.AdjEnd[2] := 'ое';
caseParam.AdjEnd[3] := 'ого';
caseParam.AdjEnd[4] := 'ий';
caseParam.AdjEnd[5] := 'ее';
caseParam.AdjEnd[6] := 'ую';
caseParam.NounEnd[1] := '';
caseParam.NounEnd[2] := 'у';
caseParam.NounEnd[3] := 'е';
caseParam.NounEnd[4] := 'о';
caseParam.NounEnd[5] := 'ы';
caseParam.NounEnd[6] := 'ю';
caseParam.NounEnd[7] := 'ь';
_caseParams[4] := caseParam;
////////////////////////////////////////////////////////////////////////
// Творительный падеж (кем, чем)
////////////////////////////////////////////////////////////////////////
ClearAdvRecord(caseParam);
caseParam.AdjEnd[1] := 'ым';
caseParam.AdjEnd[2] := 'ым';
caseParam.AdjEnd[3] := 'ым';
caseParam.AdjEnd[4] := 'им';
caseParam.AdjEnd[5] := 'им';
caseParam.AdjEnd[6] := 'ой';
caseParam.NounEnd[1] := 'ом';
caseParam.NounEnd[2] := 'ой';
caseParam.NounEnd[3] := 'ем';
caseParam.NounEnd[4] := 'ом';
caseParam.NounEnd[5] := 'ами';
caseParam.NounEnd[6] := 'ей';
caseParam.NounEnd[7] := 'ью';
_caseParams[5] := caseParam;
////////////////////////////////////////////////////////////////////////
// Предложный падеж (о ком, о чем)
////////////////////////////////////////////////////////////////////////
ClearAdvRecord(caseParam);
caseParam.AdjEnd[1] := 'ом';
caseParam.AdjEnd[2] := 'ом';
caseParam.AdjEnd[3] := 'ом';
caseParam.AdjEnd[4] := 'ом';
caseParam.AdjEnd[5] := 'ем';
caseParam.AdjEnd[6] := 'ой';
caseParam.NounEnd[1] := 'е';
caseParam.NounEnd[2] := 'е';
caseParam.NounEnd[3] := 'е';
caseParam.NounEnd[4] := 'е';
caseParam.NounEnd[5] := 'ах';
caseParam.NounEnd[6] := 'е';
caseParam.NounEnd[7] := 'и';
_caseParams[6] := caseParam;
}
end;
end.
// Использование Test.vip
#component "Test"
interface TestCase;
create view
as select
ObjRem.Name,
FpCO.Name
from
ObjRem,
FpCO;
handleEvent
cmInit:
{
var strUtils : Utils::IStringUtils;
LoadVipRef(strUtils, 'Utils::StringUtils');
_loop ObjRem // FpCO
{
var str : string;
str := ObjRem.Name; // FpCO.Name
var needStop : boolean;
needStop := false; // Для ObjRem = false для FpCO = true
LogStrToFile('c:\res.log', str +
Chr(13) +
strUtils.ConvertStatementToCase(str, csGenitiveCase, needStop) +
Chr(13) +
strUtils.ConvertStatementToCase(str, csDativeCase, needStop) +
Chr(13) +
strUtils.ConvertStatementToCase(str, csAccusativeCase, needStop) +
Chr(13) +
strUtils.ConvertStatementToCase(str, csInstrumentativeCase, needStop) +
Chr(13) +
strUtils.ConvertStatementToCase(str, csPrepositionCase, needStop) +
Chr(13));
}
ProcessText('c:\res.log', vfRunModal or vfNewTitle or vfToErase or vfMacroSize or vfEscable, 'Отчет');
}
end;
end.
Объект ремонта
----
Система контроля вибрации
Системы контроля вибрации
Системе контроля вибрации
Систему контроля вибрации
Системой контроля вибрации
Системе контроля вибрации
---
Центр ответственности
---
Служба организации общественного питания
Службы организации общественного питания
Службе организации общественного питания
Службу организации общественного питания
Службой организации общественного питания
Службе организации общественного питания
---