ночь<N><dim>:ночка
ночь<N><adj><m><sg><nom>:ночной
ночь<N><nom>:ночь
ночь<N><acc>:ночь
печь<N><dim>:печка
печь<N><adj><m><sg><nom>:печной
печь<N><nom>:печь
печь<N><acc>:печь
6 Операции с трансдьюсерами
Посмотрим на следующий трансдьюсер.
```{lexd}
PATTERNS
Noun [<N>:] Suffix[-adj] | (Suffix[adj] AdjInflection)
Noun [<N>:] NounInflection
LEXICON Noun
ночь
печь
LEXICON Suffix
<dim>:ка
<adj>:н[adj]
LEXICON AdjInflection
<m><sg><nom>:ой
LEXICON NounInflection
<nom>:
<acc>:
```
```{twol}
Alphabet
а е й к н о п ч ь ь:0;
Rules
"чк чн пишется без ь"
! например, ночьной -> ночной или печька -> печка
ь:0 <=> _ к;
_ н;
```
```{shell}
$ lexd example.lexd | hfst-txt2fst -o lexd.hfst
$ hfst-twolc -q example.twol -o twol.hfst
$ hfst-compose-intersect lexd.hfst twol.hfst -o generator.hfst
```
6.1 Некоторые команды hfst
В большинстве команд ниже работают флаги -i
— входящий файл; -o
— исходящий файл. Если -o
отсутствует, то результат печатается в консоль.
6.1.1 hfst-fst2strings
Печатает формы:
```{shell}
$ hfst-fst2strings generator.hfst
```
Также существует программа hfst-expand
, которая делает то же самое.
6.1.2 hfst-fst2txt
Печатает трансдьюсер в AT&T формате:
```{shell}
$ hfst-fst2txt generator.hfst
```
0 1 @0@ @0@ 0.000000
1 2 н н 0.000000
1 3 п п 0.000000
2 4 о о 0.000000
3 4 е е 0.000000
4 5 ч ч 0.000000
5 6 ь @0@ 0.000000
5 7 ь ь 0.000000
6 8 <N> @0@ 0.000000
7 9 <N> @0@ 0.000000
8 10 <nom> @0@ 0.000000
8 10 <acc> @0@ 0.000000
8 11 <dim> к 0.000000
8 12 <adj> н 0.000000
9 13 <nom> @0@ 0.000000
9 13 <acc> @0@ 0.000000
11 14 @0@ а 0.000000
12 15 <m> о 0.000000
13 16 @0@ @0@ 0.000000
14 16 @0@ @0@ 0.000000
15 17 <sg> й 0.000000
16 0.000000
17 14 <nom> @0@ 0.000000
6.1.3 hfst-summarise
Данная программа печатает саммари для трансдьюсера.
```{shell}
$ hfst-summarise generator.hfst
```
name: "compose(text(<stdin>), intersect(examples/twol.hfst))"
fst type: OpenFST
arc type: tropical
input symbol table: yes
output symbol table: yes
# of states: 18
# of arcs: 22
initial state: 0
# of final states: 1
# of input/output epsilons: 3
# of input epsilons: 4
# of output epsilons: 11
# of ... accessible states: ???
# of ... coaccessible states: ???
# of ... connected states: ???
# of ... strongly conn components: ???
expanded: ???
mutable: yes
acceptor: no
input deterministic: no
output deterministic: no
input label sorted: ???
output label sorted: ???
weighted: yes
cyclic: no
cyclic at initial state: no
topologically sorted: ???
accessible: ???
coaccessible: ???
string: ???
minimised: ???
Read 1 transducers in total.
Если вам не хочется смотреть на выдачу целиком, можно совмещать с grep
:
```{shell}
$ hfst-summarise generator.hfst | grep cyclic
```
cyclic: no
cyclic at initial state: no
6.1.4 hfst-name
Если хочется, чтобы у трансдьюсера было осмысленное имя, то можно при создании дать ему имя при помощи функции hfst-name
или hfst-edit-metadata
. Посмотреть имя трансдьюсера можно при помощи аргумента -p
(и некоторых других):
```{shell}
$ hfst-compose-intersect lexd.hfst twol.hfst | hfst-name -n 'the best fst ever' -o generator.hfst
$ hfst-name -p generator.hfst
```
"the best fst ever"
Программа hfst-edit-metadata
позволяет настроить, например, следующие поля:
--add=author=...
--add=licence=...
--add=name='...'
6.1.5 hfst-dump-alphabets
Печатает алфавит:
```{shell}
$ hfst-dump-alphabets generator.hfst
```
<N>
<acc>
<adj>
<dim>
<m>
<nom>
<sg>
@_EPSILON_SYMBOL_@
@_IDENTITY_SYMBOL_@
@_UNKNOWN_SYMBOL_@
а
е
й
к
н
о
п
ч
ь
<N>
<acc>
<adj>
<dim>
<m>
<nom>
<sg>
@_EPSILON_SYMBOL_@
а
е
й
к
н
о
п
ч
ь
Мне не очень понятно, почему он печатает все два раза, однако этот фрагмент документации намекает мне, что это решаемая проблема:
Alphabet dump options:
-1, --exclude-seen Ignore alphabets seen in automaton
-2, --exclude-metadata Ignore alphabets from headers
```{shell}
$ hfst-dump-alphabets -1 generator.hfst
```
<N>
<acc>
<adj>
<dim>
<m>
<nom>
<sg>
@_EPSILON_SYMBOL_@
@_IDENTITY_SYMBOL_@
@_UNKNOWN_SYMBOL_@
а
е
й
к
н
о
п
ч
ь
Также при помощи программы grep
полезно проверить какие-нибудь символы:
```{shell}
$ hfst-dump-alphabets -1 generator.hfst | grep ъ
```
```{shell}
$ hfst-dump-alphabets -1 generator.hfst | grep к
```
к
6.1.6 hfst-substitute
Заменяет единицы в трансдьюсере (-f
from; -t
to):
```{shell}
$ hfst-substitute -f "ч" -t "Ч" -i generator.hfst | hfst-fst2strings
```
ноЧь<N><dim>:ноЧка
ноЧь<N><adj><m><sg><nom>:ноЧной
ноЧь<N><nom>:ноЧь
ноЧь<N><acc>:ноЧь
пеЧь<N><dim>:пеЧка
пеЧь<N><adj><m><sg><nom>:пеЧной
пеЧь<N><nom>:пеЧь
пеЧь<N><acc>:пеЧь
Можно заменять конкретные соответствия (строчки в AT&T записи).
```{shell}
$ hfst-substitute -f "ь:@0@" -t "ъ:ъ" -i generator.hfst | hfst-fst2strings
```
ночъ<N><dim>:ночъка
ночъ<N><adj><m><sg><nom>:ночъной
ночь<N><nom>:ночь
ночь<N><acc>:ночь
ночъ<N><dim>:ночъка
ночъ<N><adj><m><sg><nom>:ночъной
печъ<N><dim>:печъка
печъ<N><adj><m><sg><nom>:печъной
печь<N><nom>:печь
печь<N><acc>:печь
печъ<N><dim>:печъка
печъ<N><adj><m><sg><nom>:печъной
Важно отметить, что в таком случае не работает расписывание ъ
-> ъ:ъ
.
Если хочется чего-то удалить, то следует использовать запись @0@
или @_EPSILON_SYMBOL_@
:
```{shell}
$ hfst-substitute -f "ч" -t "@0@" -i generator.hfst | hfst-fst2strings
```
ноь<N><dim>:нока
ноь<N><adj><m><sg><nom>:ноной
ноь<N><nom>:ноь
ноь<N><acc>:ноь
пеь<N><dim>:пека
пеь<N><adj><m><sg><nom>:пеной
пеь<N><nom>:пеь
пеь<N><acc>:пеь
Замены можно делать по списку, для этого нужно иметь .tsv
файл. Ниже содержимое файла label_file.tsv
:
<N> @_EPSILON_SYMBOL_@
<acc> @_EPSILON_SYMBOL_@
<adj> @_EPSILON_SYMBOL_@
<dim> @_EPSILON_SYMBOL_@
<m> @_EPSILON_SYMBOL_@
<nom> @_EPSILON_SYMBOL_@
<sg> @_EPSILON_SYMBOL_@
Мы можем удалить все теги и получить соответствие основы-формы:
```{shell}
$ hfst-substitute -F label_file.tsv -i generator.hfst | hfst-fst2strings
```
ночь:ночка
ночь:ночной
ночь
ночь
печь:печка
печь:печной
печь
печь
Опытным путем я выяснил, что это команда не будет работать с записью @0@
.
6.1.7 hfst-lookup
```{shell}
$ echo "ночь<N><dim>" | hfst-lookup generator.hfst
```
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 > ночь<N><dim> ночка 0,000000 >
Кроме того, можно на вход подавать несколько форм, разделяя их переносом строки (\n
), или программой cat
читать из файла:
```{shell}
$ echo "ночь<N><adj><m><sg><nom>\nночь<N><dim>" | hfst-lookup generator.hfst
```
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 > ночь<N><adj><m><sg><nom> ночной 0,000000 > ночь<N><dim> ночка 0,000000 >
Важно также отметить, что при помощи флага -O
можно задать тип, в котором нужно печатать результат:
xerox
```{shell}
$ echo "ночь<N><adj><m><sg><nom>\nночь<N><dim>" | hfst-lookup -O xerox generator.hfst
```
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 > ночь<N><adj><m><sg><nom> ночной 0,000000 > ночь<N><dim> ночка 0,000000 >
cg
— Constraint Grammar
```{shell}
$ echo "ночь<N><adj><m><sg><nom>\nночь<N><dim>" | hfst-lookup -O cg generator.hfst
```
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 > "<ночь<N><adj><m><sg><nom>>" ""ночной 0,000000 > "<ночь<N><dim>>" ""ночка 0,000000 >
apertium
```{shell}
$ echo "ночь<N><adj><m><sg><nom>\nночь<N><dim>" | hfst-lookup -O apertium generator.hfst
```
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 > ^ночь<N><adj><m><sg><nom>/*ночь<N><adj><m><sg><nom>$ > ^ночь<N><dim>/*ночь<N><dim>$ >
6.1.8 hfst-invert
Это очень полезная функция, так как она позволяет переворачивать трансдьюсер. В прошлом разделе мы видели генератор, а что если мы хотим наоборот - не генератор, а анализатор?
```{shell}
$ hfst-invert generator.hfst -o analyzer.hfst
$ echo "ночка" | hfst-lookup analyzer.hfst
```
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 > ночка ночь<N><dim> 0,000000 >
Любой трансдьюсер обратим — и это очень классно: вы делаете один объект, а он и анализатор, и генератор.
6.1.9 hfst-fst2fst
Возможно, Вы заметили предупреждение, которое возвращает hfst-lookup
. Оптимизированный формат можно сделать при помощи программы hfst-fst2fst
, он полезен и для других программ hfst
.
```{shell}
$ hfst-fst2fst -O analyzer.hfst -o analyzer.hfstol
$ echo "ночка" | hfst-lookup analyzer.hfstol
```
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 > ночка ночь<N><dim> 0,000000 >
Программа hfst-lookup
больше не выдает предупреждения. Еще более ожидаемый вывод будет, если использовать программу hfst-optimized-lookup
:
```{shell}
$ echo "ночка" | hfst-optimized-lookup analyzer.hfstol
```
ночка ночь<N><dim>
6.1.10 hfst-proc
и hfst-proc2
Программа hfst-proc
парсит текст. Важно, чтобы трансдьюсер был в оптимизированной форме, т. е. .hfstol
. Обратите внимание на то, как экранируется восклицательный знак.
```{shell}
$ echo "какая-то Ночка и ПЕЧЬ\!" | hfst-proc analyzer.hfstol
```
^какая/*какая$-^то/*то$ ^Ночка/Ночь<N><dim>$ ^и/*и$ ^ПЕЧЬ/ПЕЧЬ<N><acc>/ПЕЧЬ<N><nom>$!
Разные аргументы форматируют по-разному выдачу:
-C
/--cg
Constraint Grammar
```{shell}
$ echo "какая-то Ночка и ПЕЧЬ\!" | hfst-proc -C analyzer.hfstol
```
"<какая>"
"*какая"
"<то>"
"*то"
"<Ночка>"
"ночь" N dim
"<и>"
"*и"
"<ПЕЧЬ>"
"печь" N acc
"печь" N nom
-x
Xerox
```{shell}
$ echo "какая-то Ночка и ПЕЧЬ\!" | hfst-proc -x analyzer.hfstol
```
какая +?
то +?
Ночка Ночь<N><dim>
и +?
ПЕЧЬ ПЕЧЬ<N><acc>
ПЕЧЬ ПЕЧЬ<N><nom>
-w
возвращать словарный вид слова, а не тот вид, в котором он встретился в тексте.
```{shell}
$ echo "какая-то Ночка и ПЕЧЬ\!" | hfst-proc -xw analyzer.hfstol
```
какая +?
то +?
Ночка ночь<N><dim>
и +?
ПЕЧЬ печь<N><acc>
ПЕЧЬ печь<N><nom>
- флаг
-N
позволяет настроить, сколько форм будет возвращаться при анализе, например ниже исчез разборПЕЧЬ<N><nom>
.
```{shell}
$ echo "какая-то Ночка и ПЕЧЬ\!" | hfst-proc -xN 1 analyzer.hfstol
```
какая +?
то +?
Ночка Ночь<N><dim>
и +?
ПЕЧЬ ПЕЧЬ<N><acc>
Кроме того, существует программа hfst-proc2
, которая, кажется, возвращает только то, что анализатор может проанализировать:
```{shell}
$ echo "какая-то ночка и печь\!" | hfst-proc2 analyzer.hfstol
```
ночка
печь
Флаг -a
позволяет напечатать все:
```{shell}
$ echo "какая-то ночка и печь\!" | hfst-proc2 -a analyzer.hfstol
```
какая-то
ночка
и
печь
\!
Флаг -C
печатает в CoNLL-U:
```{shell}
$ echo "какая-то ночка и печь\!" | hfst-proc2 -С analyzer.hfstol
```
1 ночка _ _ _ _ _ _ _ ночь<N><dim>
2 печь _ _ _ _ _ _ _ печь<N><nom>
6.1.11 hfst-pair-test
Эта программа проверяет twol
:
```{shell}
$ echo "н о ч к а" | hfst-pair-test twol.hfst
```
Test passed.
```{shell}
$ echo "н о ч ь к а" | hfst-pair-test twol.hfst
```
Rule "чк чн пишется без ь" fails:
#:0 н о ч HERE ---> ь к а #:0
FAIL: н о ч ь к а REJECTED
Test failed.
```{shell}
$ echo "н о ч ь:0 к а" | hfst-pair-test twol.hfst
```
Test passed.
Тесты могут быть отрицательными:
```{shell}
$ echo "н о ч ь к а" | hfst-pair-test -N twol.hfst
```
Test passed.
```{shell}
$ echo "н о ч к а" | hfst-pair-test -N twol.hfst
```
FAIL: н о ч к а PASSED
Test failed.
Вообще стоит обратить внимание на мануал этой программы: она подробнее многих других программ hfst
.
6.1.12 hfst-kill-paths
Убирает все пути, содержащие некоторый символ:
```{shell}
$ hfst-kill-paths -S о generator.hfst | hfst-fst2strings
```
печь<N><acc>:печь
печь<N><nom>:печь
печь<N><dim>:печка
6.2 Некоторые операции с двумя трансдьюсерами
Создадим себе второй очень похожий трансдьюсер:
```{shell}
$ hfst-substitute -f "о" -t "О" -i generator.hfst | hfst-name -n 'transducer 2' -o generator2.hfst
```
6.2.1 hfst-compare
Сравнивает трансдьюсеры
```{shell}
$ hfst-compare generator.hfst generator.hfst
```
the best fst ever == the best fst ever
```{shell}
$ hfst-compare generator.hfst generator2.hfst
```
the best fst ever != transducer 2
```{shell}
$ hfst-compare generator.hfst analyzer.hfst
```
the best fst ever != invert(the best fst ever)
6.2.2 hfst-concatenate
Конкатенация трансдьюсеров - последнее состояние одного трансдьюсера становится начальным состоянием второго.
```{shell}
hfst-concatenate generator.hfst generator2.hfst | hfst-fst2strings | head
```
ночь<N><dim>нОчь<N><dim>:ночканОчка
ночь<N><dim>нОчь<N><adj><m><sg><nom>:ночканОчнОй
ночь<N><dim>нОчь<N><nom>:ночканОчь
ночь<N><dim>нОчь<N><acc>:ночканОчь
ночь<N><dim>печь<N><dim>:ночкапечка
ночь<N><dim>печь<N><adj><m><sg><nom>:ночкапечнОй
ночь<N><dim>печь<N><nom>:ночкапечь
ночь<N><dim>печь<N><acc>:ночкапечь
ночь<N><adj><m><sg><nom>нОчь<N><dim>:ночнойнОчка
ночь<N><adj><m><sg><nom>нОчь<N><adj><m><sg><nom>:ночнойнОчнОй
6.2.3 hfst-conjunct
или hfst-intersect
Пересечение трансдьюсеров: выделяет общее для двух трансдьюсеров.
```{shell}
hfst-conjunct generator.hfst generator2.hfst | hfst-fst2strings
```
печь<N><dim>:печка
печь<N><nom>:печь
печь<N><acc>:печь
6.2.4 hfst-disjunct
или hfst-union
Объединение трансдьюсеров.
```{shell}
hfst-disjunct generator.hfst generator2.hfst | hfst-fst2strings
```
ночь<N><dim>:ночка
ночь<N><adj><m><sg><nom>:ночной
ночь<N><nom>:ночь
ночь<N><acc>:ночь
печь<N><dim>:печка
печь<N><adj><m><sg><nom>:печной
печь<N><nom>:печь
печь<N><acc>:печь
нОчь<N><dim>:нОчка
нОчь<N><adj><m><sg><nom>:нОчнОй
нОчь<N><nom>:нОчь
нОчь<N><acc>:нОчь
печь<N><dim>:печка
печь<N><adj><m><sg><nom>:печнОй
печь<N><nom>:печь
печь<N><acc>:печь
6.2.5 hfst-subtract
или hfst-minus
Вычитание трансдьюсеров.
```{shell}
hfst-subtract generator.hfst generator2.hfst | hfst-fst2strings
```
ночь<N><dim>:ночка
ночь<N><adj><m><sg><nom>:ночной
ночь<N><nom>:ночь
ночь<N><acc>:ночь
печь<N><adj><m><sg><nom>:печной
6.3 Создание транслитераторов
Для того, чтобы создать транслитерацию, давайте запишем наши соответствия в такой файл:
```{lexd}
PATTERNS
segments
LEXICON segments
а:a
е:e
й:j
к:k
н:n
о:o
п:p
ч:tʃ
ь:
<N>
<acc>
<adj>
<dim>
<m>
<nom>
<sg>
```
```{shell}
$ lexd correspondences.lexd | hfst-txt2fst -o correspondences.hfst
$ hfst-fst2strings correspondences.hfst
```
а:a
е:e
й:j
к:k
н:n
о:o
п:p
ч:tɕ
ь:
<N>
<acc>
<adj>
<dim>
<m>
<nom>
<sg>
Получившийся трансдьюсер делает достаточно скучную вещь: если ему дать один символ он его переведет, а вот большее количество — нет:
```{shell}
echo "ч" | hfst-lookup correspondences.hfst
```
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 > ч tɕ 0,000000 >
```{shell}
echo "че" | hfst-lookup correspondences.hfst
```
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 > че че+? inf >
Чтобы наш трансдьюсер делал преобразования во всей строке, нужно его зациклить при помощи программы hfst-repeat
:
```{shell}
$ lexd correspondences.lexd | hfst-txt2fst | hfst-repeat -f 1 -o correspondences.hfst
```
```{shell}
echo "ч" | hfst-lookup correspondences.hfst
```
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 > ч tɕ 0,000000 >
```{shell}
echo "че" | hfst-lookup correspondences.hfst
```
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 > че tɕe 0,000000 >
Чтобы соединить транслитератор с уже готовыми трансдьюсерами, достаточно сделать композицию:
```{shell}
hfst-compose analyzer.hfst correspondences.hfst | hfst-fst2strings
```
ночка:notɕ<N><dim>
ночной:notɕ<N><adj><m><sg><nom>
ночь:notɕ<N><nom>
ночь:notɕ<N><acc>
печка:petɕ<N><dim>
печной:petɕ<N><adj><m><sg><nom>
печь:petɕ<N><nom>
печь:petɕ<N><acc>
```{shell}
hfst-compose generator.hfst correspondences.hfst | hfst-fst2strings
```
ночь<N><dim>:notɕka
ночь<N><adj><m><sg><nom>:notɕnoj
ночь<N><nom>:notɕ
ночь<N><acc>:notɕ
печь<N><dim>:petɕka
печь<N><adj><m><sg><nom>:petɕnoj
печь<N><nom>:petɕ
печь<N><acc>:petɕ
А что если в ходе транслитерация графема чувствительна к контексту? Например, русское <е> может транскрибироваться как [e] (мел) и как [je] (еда). Я полагаю, у решения этой проблемы есть две стратегии:
- добавлять все соответствия в файл соответствий, например,
...
че:tɕe
пе:pʲe
е:je
...
- добавлять еще один
twol
трансдьюсер, который исправляет какие-то вещи
```{lexd}
PATTERNS
segments
LEXICON segments
а:a
е:{E}
й:j
к:k
н:n
о:o
п:p
ч:tɕ
ь:
```
```{twol}
Alphabet
%{E%}:je
%{E%}:e
%{E%}:ʲe
;
Rules
"E в начале слова"
%{E%}:je <=> .#. _ ;
"E после мягких"
%{E%}:e <=> ɕ _ ;
```
```{shell}
$ hfst-twolc -q correspondences_twol.twol -o correspondences_twol.hfst
$ lexd correspondences2.lexd | hfst-txt2fst | hfst-repeat -f 1 | hfst-compose-intersect correspondences_twol.hfst -o correspondences.hfst
$ echo "ечене" | hfst-lookup correspondences.hfst
```
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 > ечене jetɕenʲe 0,000000 >
6.4 Перевод основы
Лингвисты в отличие от NLP-специалистов и компьютерных лингвистов предпочитают, чтобы основы в примерах, которые они приводят, были переведены. Этого можно достичь точно таким же набором инструментов, какой мы использовали при создании транслитератора. Создадим файл с соответствиями:
```{lexd}
PATTERNS
translations
LEXICON translations
печь:stove
ночь:night
<N>
<acc>
<adj>
<dim>
<m>
<nom>
<sg>
```
```{shell}
$ lexd ru_en.lexd | hfst-txt2fst | hfst-repeat -f 1 -o ru_en.hfst
$ hfst-compose analyzer.hfst ru_en.hfst | hfst-fst2strings
```
ночка:night<N><dim>
ночной:night<N><adj><m><sg><nom>
ночь:night<N><nom>
ночь:night<N><acc>
печка:stove<N><dim>
печной:stove<N><adj><m><sg><nom>
печь:stove<N><nom>
печь:stove<N><acc>