2 Введение в lexd
: морфология
2.1 Техническое введение
В данном разделе мы обсуждаем синтаксис программы lexd
(Swanson и Howell 2021). Данная программа работает в связке
- с бесплатным програмным обеспечением с открытым исходным кодом Helsinki Finite-State Tookit
hfst
(Lindén и др. 2011); - аналогичным инструментом от Apertium
lttoolbox
(Ortiz Rojas, Forcada, и Ramı́rez Sánchez 2005).
Это консольная программа, работающая на юниксоподобных системах. Чтобы избежать сложностей на начальных этапах курса, мы решили вначале познакомиться с синтаксисом lexd
и попробовать описывать разные языковые явления, не затрудняя всех установкой и запуском у себя на компьютере. В связи с этим мы предлагаем выучить следующие четыре команды, которые будут работать на операционных системах Linux, основанных на Debian/Ubuntu, и в Google Colab:
- скачиваем инструкции для установки
lexd
иhfst
и дальнейшей работы с ними, записанные в простом текстовом файле, которые можно прочитать, если открыть ссылку из команды. Командаmake
запускает установку. Для того, чтобы это работало в Google Colab нужно перед командой нужно поставить восклицательный знак:!curl ...
. Знак доллара означает, что дальше следует команда командной строки, не надо его никуда копировать.
```{shell}
$ curl -s https://raw.githubusercontent.com/agricolamz/2025_morphological_transducers/refs/heads/main/task_tests/Makefile -o Makefile; make
```
- дальше мы ожидаем, что вы создадите в коллабе или у себя на компьютере (если у вас Linux), файл с названием
task.lexd
. В Google Colab для этого достаточно вставить первой строкой кодового блока%%writefile task.lexd
. Вот пример такого файла:
```{lexd}
PATTERNS
VerbRoot VerbInfl
LEXICON VerbRoot
sing<v>:sing
walk<v>:walk
dance<v>:dance
LEXICON VerbInfl
<pres>:
<pres><3><sg>:s
```
- После того, как вы установили нужные программы и создали файл, можно посмотреть формы и разборы, которые генерируются трансдьюсером. Это можно сделать следующей командой (не забудьте поставить восклицательный знак перед
make
в Google Colab):
```{shell}
$ make forms
sing<v><pres>:sing
sing<v><pres><3><sg>:sings
walk<v><pres>:walk
walk<v><pres><3><sg>:walks
dance<v><pres>:dance
dance<v><pres><3><sg>:dances
```
- Кроме того можно посмотреть анализ/генерацию конкретных форм (не забудьте поставить восклицательный знак перед
make
в Google Colab):
```{shell}
$ make analysis FORM="sings"
hfst-lookup: Warning: It is not possible to perform fast lookups with OpenFST, std arc, tropical semiring format automata.
Using HFST basic transducer format and performing slow lookups
> sings sing<v><pres><3><sg> 0,000000
```
```{shell}
$ make generation FORM="walk<v><pres><3><sg>"
hfst-lookup: Warning: It is not possible to perform fast lookups with OpenFST, std arc, tropical semiring format automata.
Using HFST basic transducer format and performing slow lookups
> walk<v><pres><3><sg> walks 0,000000
```
- В ходе курса мы будем разбирать разные лингвистические задачи. У каждой задачи есть номер и автоматический тест, который его проверяет. Чтобы запустить автоматическую проверку, следует ввести команду, где первое число – номер раздела, а второе число – номер задачи. Например, для того, чтобы проверить, работает ли проверка задания, попробуйте запустить следующую команду:
```{shell}
$ make test_02_01
```
- Чтобы окончательно посмотреть все варианты, попробуйте изменить последнюю строчку файла
task.lexd
на<pres><3><sg>:S
и снова перезапустить команду:
```{shell}
$ make test_02_01
```
2.2 Программа lexd
У программы lexd
есть подробный туториал, так что данный раздел во многом опирается на него. Давайте подробнее рассмотрим lexd
файл, который мы видели в прошлом разделе:
```{lexd}
1PATTERNS
VerbRoot VerbInfl
2LEXICON VerbRoot
3sing<v>:sing
walk<v>:walk
dance<v>:dance
4LEXICON VerbInfl
5<pres>:
6<pres><3><sg>:s
```
- 1
-
Обязательный раздел
PATTERNS
, в котором каждая строка сообщает, как могут соединяться элементы из разных групп лексикона. - 2
-
Группа лексикона, которая состоит из слова
LEXICON
и имени, под которым данная группа появляется в разделеPATTERNS
- 3
- Наполнение группы. Первым идет разбор, а потом после двоеточия языковой материал. Морфологические теги принято записывать в треугольных скобках.
- 4
-
Вторая группа
LEXICON
и ее имя. - 5
- Пример нулевой морфемы.
- 6
- Пример морфемы с несколькими морфологическими тегами.
Отметим, что можно создавать свои именнованные подразделы PATTERN
, которые потом можно использовать в разделе PATTERNS
, например:
```{lexd}
PATTERNS
VerbStem Tense PersonNumber
1PATTERN VerbStem
VerbRoot
VerbRoot Causative
LEXICON VerbRoot
...
LEXICON Causative
...
LEXICON Tense
...
LEXICON PersonNumber
...
```
- 1
-
Именованный раздел
PATTERN
, который используется потом в разделеPATTERNS
.
Таким образом, в каждом файле lexd
должен быть раздел PATTERNS
, содержащий в себе переменные, которые могут быть заданы либо в разделе PATTERN
, либо в разделе LEXICON
, либо их анонимные варианты (см. раздел Раздел 2.2.2). Также разные разделы можно переименовывать при помощи группы ALIAS
(см. мануал). Комментарии можно оформлять при помощи хеша #
.
2.2.1 Операторы
Квантификация напоминает регулярные выражения:
?
— ноль или один раз*
— ноль и более раз 1+
— один и более раз
```{lexd}
PATTERNS
Root Negation?
LEXICON Root
...
LEXICON Negation
...
```
```{lexd}
PATTERNS
Root
Root Negation
LEXICON Root
...
LEXICON Negation
...
```
|
— оператор или (можно с пробелами вокруг)
```{lexd}
PATTERNS
Root PastInflection|PresentInflection
LEXICON Root
...
LEXICON PastInflection
...
LEXICON PresentInflection
...
```
```{lexd}
PATTERNS
Root PastInflection
Root PresentInflection
LEXICON Root
...
LEXICON PastInflection
...
LEXICON PresentInflection
...
```
- Кроме того есть операторы, названные в матералах
lexd
ситом,>
и<
:
```{lexd}
PATTERNS
VerbRoot > TAM > CLITICS
LEXICON Root
...
LEXICON TAM
...
LEXICON CLITICS
...
```
```{lexd}
PATTERNS
VerbRoot
VerbRoot TAM
VerbRoot TAM CLITICS
LEXICON Root
...
LEXICON TAM
...
LEXICON CLITICS
...
```
2.2.2 Анонимные разделы
Некоторые фрагменты аннотации можно вставлять прямо в раздел PATTERNS
. Для этого используются квадртные скобки.
```{lexd}
PATTERNS
NounStem [<n>:] NounNumber
LEXICON NounStem
sock
ninja
LEXICON NounNumber
<sg>:
<pl>:s
```
```{lexd}
PATTERNS
NounStem NounNumber
LEXICON NounStem
sock<n>:sock
ninja<n>:ninja
LEXICON NounNumber
<sg>:
<pl>:s
```
```{lexd}
PATTERNS
NounStem NounTag NounNumber
1LEXICON NounTag
<n>:
LEXICON NounStem
sock
ninja
LEXICON NounNumber
<sg>:
<pl>:s
```
- 1
-
Новый раздел
LEXICON
.
В мануале это трюк назван Anonymous LEXICON, видимо, потому что предполагается, что мы таким образом избегаем создания дополнительного раздела LEXICON
(см. развернутый пример 2).
По аналогии с анонимным разделом LEXICON
есть анонимный раздел PATTERN
. Для этого используются круглые скобки.
```{lexd}
PATTERNS
(VerbRoot Causative?) | AuxRoot Tense PersonNumber
LEXICON VerbRoot
...
LEXICON Causative
...
LEXICON AuxRoot
...
LEXICON Tense
...
LEXICON PersonNumber
...
```
```{lexd}
PATTERNS
VerbStem | AuxRoot Tense PersonNumber
1PATTERN VerbStem
VerbRoot Causative?
LEXICON VerbRoot
...
LEXICON Causative
...
LEXICON AuxRoot
...
LEXICON Tense
...
LEXICON PersonNumber
...
```
- 1
-
Новый раздел
PATTERN
.
2.2.3 Теги
На содержимое разделов LEXICON
можно вешать теги. Это может быть полезно, например, для моделирования словоизменительных классов. Рассмотрим пример из русского языка (славянские, индоевропейские):
```{lexd}
PATTERNS
NounStem[hard] Inflection[hard]
NounStem[soft] Inflection[soft]
LEXICON NounStem
мама:мам[hard]
папа:пап[hard]
няня:нян[soft]
Таня:Тан[soft]
LEXICON Inflection
<nom><sg>:а[hard]
<nom><sg>:я[soft]
<gen><sg>:ы[hard]
<gen><sg>:и[soft]
```
То же самое можно записать при помощи одного тега, используя операцию отмены тега:
```{lexd}
PATTERNS
NounStem[hard] Inflection[hard]
NounStem[-hard] Inflection[-hard]
LEXICON NounStem
мама:мам[hard]
папа:пап[hard]
няня:нян
буря:бур
LEXICON Inflection
<nom><sg>:а[hard]
<nom><sg>:я
<gen><sg>:ы[hard]
<gen><sg>:и
```
Однако в русском языке можно найти аффиксы, которые присоединяются к обоим типам основ, в таком случае, придется усложнить наше описание:
```{lexd}
PATTERNS
NounStem[hard] Inflection[hard]
NounStem[soft] Inflection[soft]
NounStem Inflection[-hard,-soft]
LEXICON NounStem
мама:мам[hard]
папа:пап[hard]
няня:нян[soft]
Таня:Тан[soft]
LEXICON Inflection
<nom><sg>:а[hard]
<nom><sg>:я[soft]
<gen><sg>:ы[hard]
<gen><sg>:и[soft]
<pos>:ин
```
Авторы lexd
добавили возможность взаимодействия тегов, чтобы не надо было писать одно и то же.
(A B)[x] = (A[x] B) | (A B[x])
```{lexd}
PATTERNS
(A B)[x]
LEXICON A
aaa[x]
bbb
LEXICON B
AAA[x]
BBB
```
aaaAAA
aaaBBB
bbbAAA
(A B)[-x] = A[-x] B[-x]
```{lexd}
PATTERNS
(A B)[-x]
LEXICON A
aaa[x]
bbb
LEXICON B
AAA[x]
BBB
```
bbbBBB
A[|[x,y]] = A[x] | A[y]
```{lexd}
PATTERNS
A[|[x,y]]
LEXICON A
aaa[x]
bbb[y]
ccc
```
aaa
bbb
A[^[x,y]] = A[x,-y] | A[-x,y]
```{lexd}
PATTERNS
A[^[x,y]]
LEXICON A
aaa[x]
bbb[y]
ccc[z]
ddd[x,y]
eee[x,z]
fff[y,z]
ggg
```
aaa
eee
bbb
fff
^
— очень полезный оператор, который позволяет смоделировать согласование по признакам
(A B)[^[x,y]] = (A[x,-y] B[x,-y]) | (A[-x,y] B[-x, y])
:
```{lexd}
PATTERNS
(A B)[^[x,y]]
LEXICON A
aaa[x]
bbb[y]
ccc
LEXICON B
AAA[x]
BBB[y]
CCC
```
aaaAAA
aaaCCC
cccAAA
cccBBB
bbbCCC
bbbBBB
Это позволяет смоделировать наш русский пример одной строчкой:
```{lexd}
PATTERNS
(NounStem Inflection)[^[hard,soft]]
LEXICON NounStem
мама:мам[hard]
папа:пап[hard]
няня:нян[soft]
Таня:Тан[soft]
LEXICON Inflection
<nom><sg>:а[hard]
<nom><sg>:я[soft]
<gen><sg>:ы[hard]
<gen><sg>:и[soft]
<pos>:ин
```
```{lexd}
PATTERNS
NounStem[hard] Inflection[hard]
NounStem[soft] Inflection[soft]
NounStem Inflection[-hard,-soft]
LEXICON NounStem
мама:мам[hard]
папа:пап[hard]
няня:нян[soft]
Таня:Тан[soft]
LEXICON Inflection
<nom><sg>:а[hard]
<nom><sg>:я[soft]
<gen><sg>:ы[hard]
<gen><sg>:и[soft]
<pos>:ин
```
2.2.4 Моделирование разрывных морфем: инфиксы, редупликация, семитские корни
В разеделе PATTERNS
можно перечислять разные стороны единиц (или входное и выходное значение), записанных в LEXICON
2. Это позволяет:
- опускать либо глоссы, либо морфемы (полезно для моделирования редупликации);
- иметь разный порядок глосс и морфем (но зачем?).
Вот пример моделирования дистрибутивных числительных (т. е. числительных со значением ‘по Х’) в зиловском андийском (андийские, нахско-дагестанские):
```{lexd}
PATTERNS
Numerals NumeralMarker
NumeralReduplication :Numerals Numerals NumeralMarker NumeralDistributiveMarker
LEXICON Numerals
чIе # числительное 2
лъоб # числительное 3
ойлIи # числительное 6
LEXICON NumeralMarker
<num>:гу
LEXICON NumeralDistributiveMarker
<distr>:
LEXICON NumeralReduplication
<rdp>:
```
чIе<num>:чIегу
лъоб<num>:лъобгу
ойлIи<num>:ойлIигу
<rdp>чIе<num><distr>:чIечIегу
<rdp>лъоб<num><distr>:лъоблъобгу
<rdp>ойлIи<num><distr>:ойлIиойлIигу
Кроме того для моделирования разрывных морфем, вводится номер в круглых скобках, а элементы морфемы перечисляются через пробел. Вот пример, из иврита (симитские, афразийские):
```{lexd}
PATTERNS
C(1) V(1) C(2) :V(2) C(3) V(2):
LEXICON C(3)
sh m r # соблюдать, защищать
y sh v # садиться
LEXICON V(2)
:a <v><p3><sg>:a
:o <v><pprs>:e
```
shmr<v><p3><sg>:shamar
shmr<v><pprs>:shomer
yshb<v><p3><sg>:yashab
yshb<v><pprs>:yosheb
2.2.5 Регулярные выражения
В разделе LEXICON допускаются регулярные выражения, для этого их нужно обромлять косыми чертами /
:
- группировка при помощи скобок
()
- квантификация при помощи
?
,*
, и+
. Объект квантификации должен быть обрамлен круглыми скобками. - логическое ‘или’
|
- группы символов при помощи квадратных скобок
[]
- промежутки символов [a-z]
```{lexd}
PATTERNS
SomeLexicon
LEXICON SomeLexicon
/x(y|zz)?[n-p]/
```
xyn
xyo
xyp
xzzn
xzzo
xzzp
xn
xo
xp
Это позволяет добавлять разбор неизвестных единиц в lexd
. Важно отметить, что добавление некоторых типов регулярных выражение делает циклический трансдьюсер, поэтому результат такого трансдьюссера можно посмотреть только при помощи команд make analysis FORM="..."
или make generation FORM="..."
.
```{lexd}
PATTERNS
Stem Affix
LEXICON Stem
стол
дом
/([а-я])*/
LEXICON Affix
<nom><sg>:
<gen><sg>:а
<acc><sg>:
<dat><sg>:у
<ins><sg>:ом
<loc><sg>:е
```
```{shell}
$ make analysis FORM="комом"
hfst-lookup: Warning: It is not possible to perform fast lookups with OpenFST, std arc, tropical semiring format automata.
Using HFST basic transducer format and performing slow lookups
> комом ком<ins><sg> 0,000000
комом комом<acc><sg> 0,000000
комом комом<nom><sg> 0,000000
```