995 lines
25 KiB
C
995 lines
25 KiB
C
|
! ===========================================================================
|
|||
|
!
|
|||
|
! RusMCE.h:
|
|||
|
! Системный модуль для русской грамматики
|
|||
|
! (генератор падежей, проверка глаголов, пр.)
|
|||
|
! Source encoding: CP1251
|
|||
|
!
|
|||
|
! (c) Gayev D.G. 2003
|
|||
|
!
|
|||
|
! ---------------------------------------------------------------------------
|
|||
|
|
|||
|
System_file;
|
|||
|
|
|||
|
Constant Tlimit = 31; ! (не больше)
|
|||
|
Array Tbuffer --> 3+TLimit;
|
|||
|
Array Tparse --> Tlimit;
|
|||
|
|
|||
|
! DL: слегка модифицированная версия для DictionaryLookup
|
|||
|
! (из "ParserM.h")
|
|||
|
|
|||
|
[ DL buf len
|
|||
|
i;
|
|||
|
|
|||
|
if (len == 0 || len > Tlimit) return 0;
|
|||
|
|
|||
|
Tbuffer-->0 = len;
|
|||
|
for (i = 0: i ~= len: i ++) Tbuffer-->(1+i) = buf-->i;
|
|||
|
Tbuffer-->(1+len) = 0;
|
|||
|
|
|||
|
VM_Tokenise(Tbuffer, Tparse);
|
|||
|
return Tparse-->1;
|
|||
|
];
|
|||
|
|
|||
|
! DLx:
|
|||
|
! как DL, но для поиска элементов словаря на 'term'
|
|||
|
|
|||
|
[ DLx buf len term
|
|||
|
i;
|
|||
|
if (len == 0 || len >= Tlimit) return 0;
|
|||
|
|
|||
|
Tbuffer-->0 = len+1;
|
|||
|
for (i = 0: i ~= len: i ++) Tbuffer-->(1+i) = buf-->i;
|
|||
|
Tbuffer-->(1+len) = term;
|
|||
|
Tbuffer-->(2+len) = 0;
|
|||
|
|
|||
|
VM_Tokenise(Tbuffer, Tparse);
|
|||
|
return Tparse-->1;
|
|||
|
];
|
|||
|
|
|||
|
[ CyrCharToUpperUni ch;
|
|||
|
if (ch >= $0430 && ch <=$044F) {
|
|||
|
return ch - 32;
|
|||
|
}
|
|||
|
if (ch == $0451) {
|
|||
|
return $0401; ! Ё
|
|||
|
}
|
|||
|
return ch;
|
|||
|
];
|
|||
|
|
|||
|
Attribute fem_grammar; ! (тип склонения женского рода)
|
|||
|
|
|||
|
Property casegen; ! (необязательный собственный генератор падежей объекта)
|
|||
|
|
|||
|
! # падежей (нужно парсеру)
|
|||
|
Constant LanguageCases = 6;
|
|||
|
|
|||
|
! Идентификаторы падежей
|
|||
|
Constant csOff = 0; ! Нет (отключить генератор падежей)
|
|||
|
|
|||
|
Constant csNom = 1; ! Именительный падеж (= номинатив)
|
|||
|
Constant csGen = 2; ! Родительный падеж (= генитив)
|
|||
|
Constant csDat = 3; ! Дательный падеж (= датив)
|
|||
|
Constant csAcc = 4; ! Винительный падеж (= аккузатив)
|
|||
|
Constant csIns = 5; ! Творительный падеж (= инструментал)
|
|||
|
Constant csPre = 6; ! Предложный падеж (= препозитив)
|
|||
|
|
|||
|
! Падеж по умолчанию для вывода ShortName
|
|||
|
Global csDflt = csNom;
|
|||
|
|
|||
|
! Категории объекта
|
|||
|
Constant ocSM = 1; ! Единственное число / Мужской род
|
|||
|
Constant ocSF = 2; ! Единственное число / Женский род
|
|||
|
Constant ocSN = 3; ! Единственное число / Средний род
|
|||
|
Constant ocPL = 4; ! Множественное число
|
|||
|
|
|||
|
! Категория объекта
|
|||
|
! определить категорию
|
|||
|
[ objID obj;
|
|||
|
|
|||
|
if (obj has pluralname) return ocPL;
|
|||
|
else if (obj has neuter) return ocSN;
|
|||
|
else if (obj has female) return ocSF;
|
|||
|
else if (obj has fem_grammar) return ocSF;
|
|||
|
else return ocSM;
|
|||
|
];
|
|||
|
|
|||
|
! (Режим отладки генератора падежей)
|
|||
|
Constant DEBUG_CASES = false;
|
|||
|
|
|||
|
! Основная таблица падежных суффиксов
|
|||
|
|
|||
|
Constant ADJ_TOP = 64;
|
|||
|
|
|||
|
! SM_Req: запрос к таблице падежей (#nreq)
|
|||
|
! (ед. число, мужской род)
|
|||
|
[ SM_Req csID nreq;
|
|||
|
|
|||
|
switch (nreq) {
|
|||
|
|
|||
|
! II склонение, на согласный:
|
|||
|
! (дом, снег, баран, кнут, мир, парад):
|
|||
|
! -, -а, -у, -, -ом, -е
|
|||
|
0: switch (csID) {
|
|||
|
csNom: return 0;
|
|||
|
csGen: return 'а//';
|
|||
|
csDat: return 'у//';
|
|||
|
csAcc: return 0;
|
|||
|
csIns: return 'ом';
|
|||
|
csPre: return 'е//';
|
|||
|
}
|
|||
|
|
|||
|
! II склонение, на -ь:
|
|||
|
! (снегирь, апрель, пароль, кремень, фонарь, окунь, медведь):
|
|||
|
! -ь, -я, -ю, -ь, -ем, -е
|
|||
|
1: switch (csID) {
|
|||
|
csNom: return 'ь//';
|
|||
|
csGen: return 'я//';
|
|||
|
csDat: return 'ю//';
|
|||
|
csAcc: return 'ь//';
|
|||
|
csIns: return 'ем';
|
|||
|
csPre: return 'е//';
|
|||
|
}
|
|||
|
|
|||
|
! II склонение, на -й:
|
|||
|
! (иней, лакей, зной, май):
|
|||
|
! -й, -я, -ю, -й, -ем, -е
|
|||
|
2: switch (csID) {
|
|||
|
csNom: return 'й//';
|
|||
|
csGen: return 'я//';
|
|||
|
csDat: return 'ю//';
|
|||
|
csAcc: return 'й//';
|
|||
|
csIns: return 'ем';
|
|||
|
csPre: return 'е//';
|
|||
|
}
|
|||
|
|
|||
|
! II склонение, на -ий:
|
|||
|
! (литий, планетарий, крематорий, Евгений, Василий):
|
|||
|
! -ий, -ия, -ию, -ий, -ием, -ии
|
|||
|
3: switch (csID) {
|
|||
|
csNom: return 'ий';
|
|||
|
csGen: return 'ия';
|
|||
|
csDat: return 'ию';
|
|||
|
csAcc: return 'ий';
|
|||
|
csIns: return 'ием';
|
|||
|
csPre: return 'ии';
|
|||
|
}
|
|||
|
|
|||
|
! Прилагательные, на -ый:
|
|||
|
! (красный, белый, сильный, здоровый):
|
|||
|
! -ый, -ого, -ому, -ый, -ым, -ом
|
|||
|
64: switch (csID) {
|
|||
|
csNom: return 'ый';
|
|||
|
csGen: return 'ого';
|
|||
|
csDat: return 'ому';
|
|||
|
csAcc: return 'ый';
|
|||
|
csIns: return 'ым';
|
|||
|
csPre: return 'ом';
|
|||
|
}
|
|||
|
|
|||
|
! Прилагательные, на -ой:
|
|||
|
! (большой, злой, плохой, лихой, нагой):
|
|||
|
! -ой, -ого, -ому, -ой, -ым, -ом
|
|||
|
65: switch (csID) {
|
|||
|
csNom: return 'ой';
|
|||
|
csGen: return 'ого';
|
|||
|
csDat: return 'ому';
|
|||
|
csAcc: return 'ой';
|
|||
|
csIns: return 'ым';
|
|||
|
csPre: return 'ом';
|
|||
|
}
|
|||
|
|
|||
|
! Прилагательные, на -ий:
|
|||
|
! (синий, средний, хороший):
|
|||
|
! -ий, -его, -ему, -ий, -им, -ем
|
|||
|
66: switch (csID) {
|
|||
|
csNom: return 'ий';
|
|||
|
csGen: return 'его';
|
|||
|
csDat: return 'ему';
|
|||
|
csAcc: return 'ий';
|
|||
|
csIns: return 'им';
|
|||
|
csPre: return 'ем';
|
|||
|
}
|
|||
|
|
|||
|
} ! switch (nreq)
|
|||
|
|
|||
|
return -1;
|
|||
|
]; ! SM_Req
|
|||
|
|
|||
|
! SF_Req: запрос к таблице падежей (#nreq)
|
|||
|
! (ед. число, женский род)
|
|||
|
[ SF_Req csID nreq;
|
|||
|
|
|||
|
switch (nreq) {
|
|||
|
|
|||
|
! I склонение, на -а:
|
|||
|
! (вода, стрела, зола, комната):
|
|||
|
! -а, -ы, -е, -у, -ой, -е
|
|||
|
0: switch (csID) {
|
|||
|
csNom: return 'а//';
|
|||
|
csGen: return 'ы//';
|
|||
|
csDat: return 'е//';
|
|||
|
csAcc: return 'у//';
|
|||
|
csIns: return 'ой';
|
|||
|
csPre: return 'е//';
|
|||
|
}
|
|||
|
|
|||
|
! I склонение, на -я:
|
|||
|
! (земля, башня):
|
|||
|
! -я, -и, -е, -ю, -ей, -е
|
|||
|
1: switch (csID) {
|
|||
|
csNom: return 'я//';
|
|||
|
csGen: return 'и//';
|
|||
|
csDat: return 'е//';
|
|||
|
csAcc: return 'ю//';
|
|||
|
csIns: return 'ей';
|
|||
|
csPre: return 'е//';
|
|||
|
}
|
|||
|
|
|||
|
! III склонение, на -ь:
|
|||
|
! (метель, ночь, медь, осень):
|
|||
|
! -ь, -и, -и, -ь, -ью, -и
|
|||
|
2: switch (csID) {
|
|||
|
csNom: return 'ь//';
|
|||
|
csGen: return 'и//';
|
|||
|
csDat: return 'и//';
|
|||
|
csAcc: return 'ь//';
|
|||
|
csIns: return 'ью';
|
|||
|
csPre: return 'и//';
|
|||
|
}
|
|||
|
|
|||
|
! I склонение, на -ия:
|
|||
|
! (сессия, лекция, пародия, агония):
|
|||
|
! -ия, -ии, -ии, -ию, -ией, -ии
|
|||
|
3: switch (csID) {
|
|||
|
csNom: return 'ия';
|
|||
|
csGen: return 'ии';
|
|||
|
csDat: return 'ии';
|
|||
|
csAcc: return 'ию';
|
|||
|
csIns: return 'ией';
|
|||
|
csPre: return 'ии';
|
|||
|
}
|
|||
|
|
|||
|
! Прилагательные, на -ая:
|
|||
|
! (красная, большая, приятная):
|
|||
|
! -ая, -ой, -ой, -ую, -ой, -ой
|
|||
|
64: switch (csID) {
|
|||
|
csNom: return 'ая';
|
|||
|
csGen: return 'ой';
|
|||
|
csDat: return 'ой';
|
|||
|
csAcc: return 'ую';
|
|||
|
csIns: return 'ой';
|
|||
|
csPre: return 'ой';
|
|||
|
}
|
|||
|
|
|||
|
! Прилагательные, на -яя:
|
|||
|
! (синяя, средняя):
|
|||
|
! -яя, -ей, -ей, -юю, -ей, -ей
|
|||
|
65: switch (csID) {
|
|||
|
csNom: return 'яя';
|
|||
|
csGen: return 'ей';
|
|||
|
csDat: return 'ей';
|
|||
|
csAcc: return 'юю';
|
|||
|
csIns: return 'ей';
|
|||
|
csPre: return 'ей';
|
|||
|
}
|
|||
|
|
|||
|
} ! switch (nreq)
|
|||
|
|
|||
|
return -1;
|
|||
|
]; ! SF_Req
|
|||
|
|
|||
|
! SN_Req: запрос к таблице падежей (#nreq)
|
|||
|
! (ед. число, средний род)
|
|||
|
[ SN_Req csID nreq;
|
|||
|
|
|||
|
switch (nreq) {
|
|||
|
|
|||
|
! II склонение, на -о:
|
|||
|
! (облако, озеро, утро, ведро, зеркало):
|
|||
|
! -о, -а, -у, -о, -ом, -е
|
|||
|
0: switch (csID) {
|
|||
|
csNom: return 'о//';
|
|||
|
csGen: return 'а//';
|
|||
|
csDat: return 'у//';
|
|||
|
csAcc: return 'о//';
|
|||
|
csIns: return 'ом';
|
|||
|
csPre: return 'е//';
|
|||
|
}
|
|||
|
|
|||
|
! II склонение, на -е:
|
|||
|
! (поле, ложе):
|
|||
|
! -е, -я, -ю, -е, -ем, -е
|
|||
|
1: switch (csID) {
|
|||
|
csNom: return 'е//';
|
|||
|
csGen: return 'я//';
|
|||
|
csDat: return 'ю//';
|
|||
|
csAcc: return 'е//';
|
|||
|
csIns: return 'ем';
|
|||
|
csPre: return 'е//';
|
|||
|
}
|
|||
|
|
|||
|
! II склонение, на -ие:
|
|||
|
! (известие, занятие, приветствие, мышление):
|
|||
|
! -ие, -ия, -ию, -ие, -ием, -ии
|
|||
|
2: switch (csID) {
|
|||
|
csNom: return 'ие';
|
|||
|
csGen: return 'ия';
|
|||
|
csDat: return 'ию';
|
|||
|
csAcc: return 'ие';
|
|||
|
csIns: return 'ием';
|
|||
|
csPre: return 'ии';
|
|||
|
}
|
|||
|
|
|||
|
! Разносклоняемое, на -я:
|
|||
|
! (время, племя, имя, знамя):
|
|||
|
! -я, -ени, -ени, -я, -енем, -ени
|
|||
|
3: switch (csID) {
|
|||
|
csNom: return 'я//';
|
|||
|
csGen: return 'ени';
|
|||
|
csDat: return 'ени';
|
|||
|
csAcc: return 'я//';
|
|||
|
csIns: return 'енем';
|
|||
|
csPre: return 'ени';
|
|||
|
}
|
|||
|
|
|||
|
! Прилагательные, на -ое:
|
|||
|
! (красное, малое, мертвое):
|
|||
|
! -ое, -ого, -ому, -ое, -ым, -ом
|
|||
|
64: switch (csID) {
|
|||
|
csNom: return 'ое';
|
|||
|
csGen: return 'ого';
|
|||
|
csDat: return 'ому';
|
|||
|
csAcc: return 'ое';
|
|||
|
csIns: return 'ым';
|
|||
|
csPre: return 'ом';
|
|||
|
}
|
|||
|
|
|||
|
! Прилагательные, на -ее:
|
|||
|
! (синее, среднее):
|
|||
|
! -ее, -его, -ему, -ее, -им, -ем
|
|||
|
65: switch (csID) {
|
|||
|
csNom: return 'ее';
|
|||
|
csGen: return 'его';
|
|||
|
csDat: return 'ему';
|
|||
|
csAcc: return 'ее';
|
|||
|
csIns: return 'им';
|
|||
|
csPre: return 'ем';
|
|||
|
}
|
|||
|
|
|||
|
} ! switch (nreq)
|
|||
|
|
|||
|
return -1;
|
|||
|
]; ! SN_Req
|
|||
|
|
|||
|
! PL_Req: запрос к таблице падежей (#nreq)
|
|||
|
! (мн. число)
|
|||
|
[ PL_Req csID nreq;
|
|||
|
|
|||
|
switch (nreq) {
|
|||
|
|
|||
|
! TMP: нерегулярность Gen Pl
|
|||
|
|
|||
|
! Множественное, на -и:
|
|||
|
! (овраги, цели, недели):
|
|||
|
! -и, -ов/-ей/-, -ам/-ям, -и, -ами/-ями, -ах/-ях
|
|||
|
0: switch (csID) {
|
|||
|
csNom: return 'и//';
|
|||
|
csGen: return 'ев'; ! TMP: не всегда! - ей,
|
|||
|
csDat: return 'ям';
|
|||
|
csAcc: return 'и//';
|
|||
|
csIns: return 'ями';
|
|||
|
csPre: return 'ях';
|
|||
|
}
|
|||
|
|
|||
|
! Множественное, на -ы:
|
|||
|
! (работы, солдаты, заботы, закаты):
|
|||
|
! -ы, -ов/-ей/-, -ам/-ям, -и, -ами/-ями, -ах/-ях
|
|||
|
1: switch (csID) {
|
|||
|
csNom: return 'ы//';
|
|||
|
csGen: return 'ов'; ! TMP: не всегда!
|
|||
|
csDat: return 'ам';
|
|||
|
csAcc: return 'ы//';
|
|||
|
csIns: return 'ами';
|
|||
|
csPre: return 'ах';
|
|||
|
}
|
|||
|
|
|||
|
! Множественное, на -а:
|
|||
|
! (облака, дома, номера):
|
|||
|
! -а, -ов, -ам, -а, -ами, -ах
|
|||
|
2: switch (csID) {
|
|||
|
csNom: return 'а//';
|
|||
|
csGen: return 'ов';
|
|||
|
csDat: return 'ам';
|
|||
|
csAcc: return 'а//';
|
|||
|
csIns: return 'ами';
|
|||
|
csPre: return 'ах';
|
|||
|
}
|
|||
|
|
|||
|
! Множественное, на -я:
|
|||
|
! (поля, моря, якоря):
|
|||
|
! -я, -ей, -ям, -я, -ями, -ях
|
|||
|
3: switch (csID) {
|
|||
|
csNom: return 'я//';
|
|||
|
csGen: return 'ей';
|
|||
|
csDat: return 'ям';
|
|||
|
csAcc: return 'я//';
|
|||
|
csIns: return 'ями';
|
|||
|
csPre: return 'ях';
|
|||
|
}
|
|||
|
|
|||
|
! Множественное, на -ья:
|
|||
|
! (листья, деревья, коренья, стулья, перья):
|
|||
|
! -ья, -ьев, -ьям, -ья, -ьями, -ьях
|
|||
|
4: switch (csID) {
|
|||
|
csNom: return 'ья';
|
|||
|
csGen: return 'ьев';
|
|||
|
csDat: return 'ьям';
|
|||
|
csAcc: return 'ья';
|
|||
|
csIns: return 'ьями';
|
|||
|
csPre: return 'ьях';
|
|||
|
}
|
|||
|
|
|||
|
! Множественное, на -ия:
|
|||
|
! (изделия, решения, стремления, понятия):
|
|||
|
! -ия, -ий, -иям, -ия, -иями, -иях
|
|||
|
5: switch (csID) {
|
|||
|
csNom: return 'ия';
|
|||
|
csGen: return 'ий';
|
|||
|
csDat: return 'иям';
|
|||
|
csAcc: return 'ия';
|
|||
|
csIns: return 'иями';
|
|||
|
csPre: return 'иях';
|
|||
|
}
|
|||
|
|
|||
|
! Множественное, на -ии:
|
|||
|
! (станции, реляции, апатии):
|
|||
|
! -ия, -ий, -иям, -ия, -иями, -иях
|
|||
|
6: switch (csID) {
|
|||
|
csNom: return 'ии';
|
|||
|
csGen: return 'ий';
|
|||
|
csDat: return 'иям';
|
|||
|
csAcc: return 'ии';
|
|||
|
csIns: return 'иями';
|
|||
|
csPre: return 'иях';
|
|||
|
}
|
|||
|
|
|||
|
! Прилагательные, на -ые:
|
|||
|
! (красные, опасные, тяжелые):
|
|||
|
! -ые, -ых, -ым, -ые, -ыми, -ых
|
|||
|
64: switch (csID) {
|
|||
|
csNom: return 'ые';
|
|||
|
csGen: return 'ых';
|
|||
|
csDat: return 'ым';
|
|||
|
csAcc: return 'ые';
|
|||
|
csIns: return 'ыми';
|
|||
|
csPre: return 'ых';
|
|||
|
}
|
|||
|
|
|||
|
! Прилагательные, на -ие:
|
|||
|
! (синие, легкие, пологие):
|
|||
|
! -ие, -их, -им, -ие, -ими, -их
|
|||
|
65: switch (csID) {
|
|||
|
csNom: return 'ие';
|
|||
|
csGen: return 'их';
|
|||
|
csDat: return 'им';
|
|||
|
csAcc: return 'ие';
|
|||
|
csIns: return 'ими';
|
|||
|
csPre: return 'их';
|
|||
|
}
|
|||
|
|
|||
|
} ! switch (nreq)
|
|||
|
|
|||
|
return -1;
|
|||
|
]; ! PL_Req
|
|||
|
|
|||
|
! Ending PostProcess (as after 'prch')
|
|||
|
[ EndingPost u prch;
|
|||
|
if (u) {
|
|||
|
! Модификация после 'г'/'к'/'х'/'ж'/'ш'/'ч'/'щ':
|
|||
|
! сапог -> сапоги, клубок -> клубки, сполох -> сполохи
|
|||
|
if (prch == 'г' or 'к' or 'х' or 'ж' or 'ш' or 'ч' or 'щ')
|
|||
|
switch (u) {
|
|||
|
'ы//': return 'и//';
|
|||
|
'ый': return 'ий';
|
|||
|
'ые': return 'ие';
|
|||
|
'ым': return 'им';
|
|||
|
'ыми': return 'ими';
|
|||
|
'ых': return 'их';
|
|||
|
}
|
|||
|
|
|||
|
! TMP: больше вариантов!
|
|||
|
|
|||
|
! после ц: ов, ом -> ев, ем (если окончание безударное)
|
|||
|
! после ж, ш: я -> а, ю -> у
|
|||
|
}
|
|||
|
|
|||
|
return u;
|
|||
|
];
|
|||
|
|
|||
|
! Ending PreProcess (as after 'prch')
|
|||
|
[ EndingPre u prch;
|
|||
|
if (u) {
|
|||
|
if (prch == 'г' or 'к' or 'х' or 'ж' or 'ш' or 'ч' or 'щ')
|
|||
|
switch (u) {
|
|||
|
'и//': return 'ы//';
|
|||
|
'ий': return 'ый';
|
|||
|
'ие': return 'ые';
|
|||
|
'им': return 'ым';
|
|||
|
'ими': return 'ыми';
|
|||
|
'их': return 'ых';
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return u;
|
|||
|
];
|
|||
|
|
|||
|
! CCaseEnd:
|
|||
|
! перевести падежное окончание (start..end) в соответствующий падеж (csID)
|
|||
|
! ocFN - генератор окончаний; disc - дискриминатор; prch - символ перед окончанием
|
|||
|
[ CCaseEnd start end csID ocFN disc prch
|
|||
|
i u v;
|
|||
|
|
|||
|
v = EndingPre (DL (start, (end-start)/4), prch);
|
|||
|
|
|||
|
! Выполнить поиск по таблицам...
|
|||
|
for (i = 0: : ++ i) {
|
|||
|
u = indirect (ocFN, csNom, i);
|
|||
|
|
|||
|
if (u == -1) {
|
|||
|
if (i >= ADJ_TOP) ! (больше нет вариантов)
|
|||
|
{ print "?"; return; }
|
|||
|
else ! (прилагательные)
|
|||
|
{ i = ADJ_TOP - 1; }
|
|||
|
} else if (u == v) {
|
|||
|
|
|||
|
if (disc) { -- disc; continue; }
|
|||
|
|
|||
|
if (csID ~= csNom) u = EndingPost (indirect (ocFN, csID, i), prch);
|
|||
|
else u = EndingPost (u, prch);
|
|||
|
|
|||
|
if (u) print (address) u;
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
];
|
|||
|
|
|||
|
! Специфичная версия для 'LanguageRefers'
|
|||
|
|
|||
|
[ EndingLookup addr len csID
|
|||
|
v u ocFN i;
|
|||
|
|
|||
|
if (csID == 0) rtrue; !! (любой падеж допустим)
|
|||
|
|
|||
|
if (len ~= 0) {
|
|||
|
v = DL (addr, len);
|
|||
|
if (v == 0) rfalse;
|
|||
|
}
|
|||
|
else v = 0;
|
|||
|
|
|||
|
ocFN = SM_Req;
|
|||
|
|
|||
|
for (::) {
|
|||
|
for (i = 0: : ++ i) {
|
|||
|
u = indirect (ocFN, csID, i);
|
|||
|
|
|||
|
if (u == -1) {
|
|||
|
if (i >= ADJ_TOP) break; ! (больше нет вариантов)
|
|||
|
else i = ADJ_TOP - 1; ! (прилагательные)
|
|||
|
}
|
|||
|
else if (u == v) rtrue;
|
|||
|
}
|
|||
|
|
|||
|
switch (ocFN) {
|
|||
|
SM_Req: ocFN = SF_Req;
|
|||
|
SF_Req: ocFN = SN_Req;
|
|||
|
SN_Req: ocFN = PL_Req;
|
|||
|
PL_Req: rfalse; ! (больше нет вариантов)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
rfalse;
|
|||
|
];
|
|||
|
|
|||
|
!
|
|||
|
! Проверить корректность глагольного суффикса
|
|||
|
!
|
|||
|
[ IsVerbSuffix start len;
|
|||
|
|
|||
|
! ("-ся|-сь": убрать)
|
|||
|
if (len >= 2 && start-->(len-2) == 'с' && start-->(len-1) == 'я' or 'ь')
|
|||
|
len = len - 2;
|
|||
|
|
|||
|
if (len == 1 && start-->0 == 'и' or 'ь') rtrue;
|
|||
|
|
|||
|
! "[аеиоуыюя]([ийь]|ть)"
|
|||
|
if (start-->0 == 'а' or 'е' or 'и' or 'о' or 'у' or 'ы' or 'ю' or 'я') {
|
|||
|
start = start + 4;
|
|||
|
len--;
|
|||
|
|
|||
|
if (len == 1 && start-->0 == 'й') rtrue;
|
|||
|
}
|
|||
|
|
|||
|
! "ти|ть"
|
|||
|
if (len == 2 && start-->0 == 'т' && start-->1 == 'ь' or 'и') rtrue;
|
|||
|
|
|||
|
! "нь|ни|нуть"
|
|||
|
if (start-->0 == 'н' &&
|
|||
|
((len == 2 && start-->1 == 'и' or 'ь') ||
|
|||
|
(len == 4 && start-->1 == 'у' && start-->2 == 'т' && start-->3 == 'ь')))
|
|||
|
rtrue;
|
|||
|
|
|||
|
rfalse;
|
|||
|
];
|
|||
|
|
|||
|
!
|
|||
|
! Проверить корректность глагольного префикса
|
|||
|
!
|
|||
|
[ IsVerbPrefix start len
|
|||
|
w;
|
|||
|
|
|||
|
w = DL (start, len);
|
|||
|
if (w == 0) return false;
|
|||
|
|
|||
|
return w ==
|
|||
|
'в//' or 'вз' or 'во' or 'вы' or
|
|||
|
'до' or
|
|||
|
'за' or
|
|||
|
'из' or 'ис' or
|
|||
|
'на' or
|
|||
|
'о//' or 'об' or 'обо' or 'от' or 'ото' or
|
|||
|
'по' or 'под' or 'подо' or 'пре' or 'при' or 'про' or 'пере' or
|
|||
|
'раз' or 'рас' or
|
|||
|
'с//' or 'со' or 'съ' or 'у//';
|
|||
|
];
|
|||
|
|
|||
|
!
|
|||
|
! Проверить корректность глагола (#wnum)
|
|||
|
!
|
|||
|
[ LanguageIsVerb buffer parse wnum
|
|||
|
adr beg len end w;
|
|||
|
|
|||
|
adr = buffer + (parse-->(wnum*3))*4;
|
|||
|
len = parse-->(wnum*3-1);
|
|||
|
|
|||
|
w = DLx (adr, len, '!');
|
|||
|
if (w) return w;
|
|||
|
|
|||
|
for (end = len: end > 0: -- end) {
|
|||
|
if (end == len || IsVerbSuffix (adr + end * 4, len - end))
|
|||
|
for (beg = 0: beg < end: ++ beg)
|
|||
|
if (beg == 0 || IsVerbPrefix (adr, beg)) {
|
|||
|
w = DL (adr + beg * 4, end - beg);
|
|||
|
if (w ~= 0 && (w->#dict_par1 & 1) ~= 0)
|
|||
|
return w; ! (verb entry found)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return 0;
|
|||
|
];
|
|||
|
|
|||
|
! Расшифровка глаголов (LanguageVerb):
|
|||
|
! просмотреть объекты в VerbDepot
|
|||
|
|
|||
|
[ LanguageVerb word
|
|||
|
obj;
|
|||
|
|
|||
|
objectloop (obj in VerbDepot) {
|
|||
|
if (WordInProperty (word, obj, name))
|
|||
|
{ print (object) obj; rtrue; }
|
|||
|
}
|
|||
|
|
|||
|
rfalse;
|
|||
|
];
|
|||
|
|
|||
|
! Падеж по умолчанию для вывода LanguageRefers
|
|||
|
Global csLR = 0;
|
|||
|
Global csLRU = 0;
|
|||
|
|
|||
|
! Обработчик соответствующего символа парсера
|
|||
|
[ c_token idtok csID
|
|||
|
retval;
|
|||
|
|
|||
|
csLR = csID;
|
|||
|
csLRU = csID; ! последний падеж, который вызывался
|
|||
|
|
|||
|
retval = ParseToken (ELEMENTARY_TT, idtok);
|
|||
|
|
|||
|
csLR = 0;
|
|||
|
|
|||
|
return retval;
|
|||
|
];
|
|||
|
|
|||
|
! LanguageRefers
|
|||
|
! Запрос от парсера:
|
|||
|
! может ли слово #wnum в данном контексте обращаться к объекту obj?
|
|||
|
|
|||
|
[ LanguageRefers obj wnum
|
|||
|
adr len end w csID;
|
|||
|
|
|||
|
adr = WordAddress(wnum); len = WordLength(wnum);
|
|||
|
|
|||
|
! Для компасных направлений -- упрощенная обработка
|
|||
|
if (parent (obj) == Compass) {
|
|||
|
w = DL (adr, len);
|
|||
|
if (w ~= 0 && WordInProperty (w, obj, name)) rtrue;
|
|||
|
rfalse;
|
|||
|
}
|
|||
|
|
|||
|
! Для мужских одушевленных предметов Acc -> Gen
|
|||
|
csID = csLR;
|
|||
|
if (csID == csAcc && obj has animate && obj has male && obj hasnt fem_grammar)
|
|||
|
csID = csGen;
|
|||
|
|
|||
|
for (end = len: end ~= 0: -- end) {
|
|||
|
w = DL (adr, end);
|
|||
|
if (w ~= 0 && WordInProperty (w, obj, name) && EndingLookup (adr + end * 4, len - end, csID))
|
|||
|
rtrue;
|
|||
|
}
|
|||
|
|
|||
|
rfalse;
|
|||
|
];
|
|||
|
|
|||
|
Constant ScrLen = 200;
|
|||
|
Array Scratch --> ScrLen;
|
|||
|
|
|||
|
! CCase:
|
|||
|
! перевести имя объекта (obj) в соответствующий падеж (csID)
|
|||
|
|
|||
|
[ CCase obj csID ucase as_obj
|
|||
|
i dlm limit ocFN;
|
|||
|
|
|||
|
#iftrue DEBUG_CASES;
|
|||
|
|
|||
|
! (отладочный вывод)
|
|||
|
csLabel (csID);
|
|||
|
print " (", (object) obj, ")";
|
|||
|
|
|||
|
#ifnot;
|
|||
|
|
|||
|
if (as_obj == false && obj == player) {
|
|||
|
if (ucase) {
|
|||
|
switch (csID) {
|
|||
|
csNom: print "Ты";
|
|||
|
csGen: print "Себя";
|
|||
|
csDat: print "Себе";
|
|||
|
csAcc: print "Себя";
|
|||
|
csIns: print "Собой";
|
|||
|
csPre: print "Себе";
|
|||
|
}
|
|||
|
} else {
|
|||
|
switch (csID) {
|
|||
|
csNom: print "ты";
|
|||
|
csGen: print "себя";
|
|||
|
csDat: print "себе";
|
|||
|
csAcc: print "себя";
|
|||
|
csIns: print "собой";
|
|||
|
csPre: print "себе";
|
|||
|
}
|
|||
|
}
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
switch (objID (obj)) {
|
|||
|
ocSM: ocFN = SM_Req;
|
|||
|
ocSF: ocFN = SF_Req;
|
|||
|
ocSN: ocFN = SN_Req;
|
|||
|
ocPL: ocFN = PL_Req;
|
|||
|
default: return;
|
|||
|
}
|
|||
|
|
|||
|
! Для мужских одушевленных предметов Acc -> Gen
|
|||
|
if (csID == csAcc && obj has animate &&
|
|||
|
obj has male && obj hasnt fem_grammar)
|
|||
|
csID = csGen;
|
|||
|
|
|||
|
if (csID ~= 0) {
|
|||
|
Scratch-->0 = VM_PrintToBuffer(Scratch, ScrLen, obj);
|
|||
|
|
|||
|
if (ucase) {
|
|||
|
Scratch-->1 = CyrCharToUpperUni(Scratch-->1);
|
|||
|
}
|
|||
|
|
|||
|
dlm = 0;
|
|||
|
limit = Scratch-->0;
|
|||
|
for (i = 1: i <= limit: ++ i) {
|
|||
|
if (Scratch-->i == '/') {
|
|||
|
if (dlm == 0) {
|
|||
|
dlm = Scratch + i * 4;
|
|||
|
} else {
|
|||
|
CCaseF (obj, ocFN, csID, dlm + 4, Scratch + i * 4);
|
|||
|
dlm = 0;
|
|||
|
}
|
|||
|
} else {
|
|||
|
if (dlm ~= 0 && Scratch-->i == ' ') {
|
|||
|
CCaseF (obj, ocFN, csID, dlm + 4, Scratch + i * 4);
|
|||
|
dlm = 0;
|
|||
|
}
|
|||
|
|
|||
|
if (dlm == 0) print (char) (Scratch-->i);
|
|||
|
}
|
|||
|
}
|
|||
|
!
|
|||
|
if (dlm ~= 0) {
|
|||
|
CCaseF (obj, ocFN, csID, dlm + 4, Scratch + i * 4);
|
|||
|
}
|
|||
|
} else {
|
|||
|
print (object) obj;
|
|||
|
}
|
|||
|
|
|||
|
#endif;
|
|||
|
];
|
|||
|
|
|||
|
[ CCaseF obj ocFN csID beg end disc;
|
|||
|
|
|||
|
! (discriminator present?)
|
|||
|
while (end-->(-1) == '!') { -- end; ++ disc; }
|
|||
|
|
|||
|
if (obj provides casegen && obj.casegen (beg, end, csID));
|
|||
|
else CCaseEnd (beg, end, csID, ocFN, disc, beg-->(-2));
|
|||
|
|
|||
|
];
|
|||
|
|
|||
|
! Вывод краткого имени объекта (через CCase)
|
|||
|
[ LanguagePrintShortName obj
|
|||
|
sn;
|
|||
|
|
|||
|
sn = short_name;
|
|||
|
|
|||
|
if (obj provides sn && PrintOrRun(obj, sn, 1) ~= 0) rtrue;
|
|||
|
|
|||
|
CCase (obj, csDflt, false);
|
|||
|
|
|||
|
rtrue;
|
|||
|
];
|
|||
|
|
|||
|
! Вывод списка в падеже csID
|
|||
|
[ WriteListFromCase obj flag csID
|
|||
|
rval csSV;
|
|||
|
|
|||
|
csSV = csDflt; csDflt = csID;
|
|||
|
|
|||
|
rval = WriteListFrom (obj, flag);
|
|||
|
|
|||
|
csDflt = csSV;
|
|||
|
return rval;
|
|||
|
];
|
|||
|
|
|||
|
! Подходящее местоимение для 'obj'
|
|||
|
[ Pronoun obj;
|
|||
|
print (string) (
|
|||
|
IIF (obj == player, "Ты", IIF (obj has pluralname, "Они",
|
|||
|
IIF (obj has female, "Она", IIF (obj has neuter, "Оно", "Он")))));
|
|||
|
];
|
|||
|
|
|||
|
[ PronounS obj;
|
|||
|
print (string) (
|
|||
|
IIF (obj == player, "ты", IIF (obj has pluralname, "они",
|
|||
|
IIF (obj has female, "она", IIF (obj has neuter, "оно", "он")))));
|
|||
|
];
|
|||
|
|
|||
|
! Окончание краткой формы прилагательных/причастий, согласованных с 'obj'
|
|||
|
! ("открыт[а|о|ы]", "пуст[а|о|ы]")
|
|||
|
[ SAEnd obj;
|
|||
|
|
|||
|
switch (objID (obj)) {
|
|||
|
ocSM: ;
|
|||
|
ocSF: print (address) 'а//';
|
|||
|
ocSN: print (address) 'о//';
|
|||
|
ocPL: print (address) 'ы//';
|
|||
|
}
|
|||
|
];
|
|||
|
|
|||
|
! Окончание глаголов, согласованных с 'obj':
|
|||
|
! (f1 ? 1-ое : 2-ое) спряжение;
|
|||
|
! f2 ? 'ют'/'ят' : 'ут'/'ат'
|
|||
|
[ VEnd obj f1 f2;
|
|||
|
|
|||
|
print (address) IIF (obj has pluralname,
|
|||
|
IIF (f1,
|
|||
|
IIF (f2, 'ют', 'ут'),
|
|||
|
IIF (f2, 'ят', 'ат')),
|
|||
|
IIF (f1, 'ет', 'ит'));
|
|||
|
];
|
|||
|
|
|||
|
! Окончание глаголов: '-ет'/'-ут'
|
|||
|
[ V1aEnd x; VEnd (x, true, false); ];
|
|||
|
|
|||
|
! Окончание глаголов: '-ет'/'-ют'
|
|||
|
[ V1bEnd x; VEnd (x, true, true); ];
|
|||
|
|
|||
|
! Окончание глаголов: '-ит'/'-ат'
|
|||
|
[ V2aEnd x; VEnd (x, false, false); ];
|
|||
|
|
|||
|
! Окончание глаголов: '-ит'/'-ят'
|
|||
|
[ V2bEnd x; VEnd (x, false, true); ];
|
|||
|
|
|||
|
! Окончание глаголов в прошедшем времени
|
|||
|
[ VPEnd noun;
|
|||
|
if (noun has pluralname) {print "и"; rtrue;}
|
|||
|
else if (noun has neuter) {print "о"; rtrue;}
|
|||
|
else if (noun has female) {print "а"; rtrue;}
|
|||
|
else {print ""; rtrue;}
|
|||
|
];
|
|||
|
|
|||
|
!
|
|||
|
! Обработчик беглых гласных
|
|||
|
! (возвращает true если обработана)
|
|||
|
!
|
|||
|
[ ICVowel csID beg end ch0 ch1;
|
|||
|
|
|||
|
if ((beg == end && ch0 == 0) || (beg + 4 == end && beg-->0 == ch0)) {
|
|||
|
if (csID == csNom || csID == csAcc) {
|
|||
|
if (ch0) print (char) ch0;
|
|||
|
}
|
|||
|
else {
|
|||
|
if (ch1) print (char) ch1;
|
|||
|
}
|
|||
|
rtrue;
|
|||
|
}
|
|||
|
|
|||
|
rfalse;
|
|||
|
];
|
|||
|
|
|||
|
[ AEnd noun;
|
|||
|
if (noun has pluralname) {print "ые"; rtrue;}
|
|||
|
else if (noun has neuter) {print "ое"; rtrue;}
|
|||
|
else if (noun has female) {print "ая"; rtrue;}
|
|||
|
else {print "ый"; rtrue;}
|
|||
|
];
|
|||
|
[ AEnd2 noun;
|
|||
|
if (noun has pluralname) {print "ие"; rtrue;}
|
|||
|
else if (noun has neuter) {print "ое"; rtrue;}
|
|||
|
else if (noun has female) {print "ая"; rtrue;}
|
|||
|
else {print "ий"; rtrue;}
|
|||
|
];
|
|||
|
[ AEnd3 noun;
|
|||
|
if (noun has pluralname) {print "ие"; rtrue;}
|
|||
|
else if (noun has neuter) {print "ое"; rtrue;}
|
|||
|
else if (noun has female) {print "ая"; rtrue;}
|
|||
|
else {print "ой"; rtrue;}
|
|||
|
];
|
|||
|
[ PEnding1 n;
|
|||
|
if (n has pluralname) {print "ими"; rtrue;}
|
|||
|
if (n has female) {print "ой"; rtrue;}
|
|||
|
print "им"; rtrue;
|
|||
|
];
|
|||
|
[ PEnding2 n;
|
|||
|
if (n has pluralname) {print "ыми"; rtrue;}
|
|||
|
if (n has female) {print "ой"; rtrue;}
|
|||
|
print "ым"; rtrue;
|
|||
|
];
|
|||
|
[ GenIt n;
|
|||
|
if (n has female) {print "её"; rtrue;}
|
|||
|
if (n has pluralname) {print "их"; rtrue;}
|
|||
|
print "его"; rtrue;
|
|||
|
];
|
|||
|
[ GenIt2 n;
|
|||
|
print "н";
|
|||
|
if (n has female) {print "её"; rtrue;}
|
|||
|
if (n has pluralname) {print "их"; rtrue;}
|
|||
|
print "его"; rtrue;
|
|||
|
];
|
|||
|
[ DatIt n;
|
|||
|
if (n has female) {print "ей"; rtrue;}
|
|||
|
if (n has pluralname) {print "им"; rtrue;}
|
|||
|
print "ему"; rtrue;
|
|||
|
];
|
|||
|
[ DatIt2 n;
|
|||
|
print "н";
|
|||
|
if (n has female) {print "ей"; rtrue;}
|
|||
|
if (n has pluralname) {print "им"; rtrue;}
|
|||
|
print "ему"; rtrue;
|
|||
|
];
|
|||
|
[ InsIt n;
|
|||
|
if (n has female) {print "ей"; rtrue;}
|
|||
|
if (n has pluralname) {print "ими"; rtrue;}
|
|||
|
print "им"; rtrue;
|
|||
|
];
|
|||
|
[ InsIt2 n;
|
|||
|
print "н";
|
|||
|
if (n has female) {print "ей"; rtrue;}
|
|||
|
if (n has pluralname) {print "ими"; rtrue;}
|
|||
|
print "им"; rtrue;
|
|||
|
];
|