SFST útmutató agglutináló nyelvekhez angolul

A Programozás Wiki wikiből

This tutorial explains, how to use SFST on an agglutinating language like Hungarian. It assumes, that you have read and understood SFST manual and SFST tutorial for English.

This tutorial explains, how to build morphology analyzer and synthesizer for agglutinating languages with SFST, handling of some special linguistic features, like vowel harmony, ephenthesis, multiple stems and assimilating suffices, and also, how to avoid high memory usage and long compilation times.

 
Contents

1. The facts of the Hungarian nouns
1.1 Conjugation
1.2 Vowel Harmony
1.3 Assimilating conjugation affices
2.  First example
2.1 Symbols
2.2 Rules
2.3 Usage of agreement variables for assimilating affices
2.4 Transformation of ending a end e
2.5 POS tag deletion
2.6 Tiny inflection logic
2.7 Lexicon read in and applying of the rules sequentially
2.8 Results
2.9 The complete fst file in one piece
2.10 Keeping the alphabet apart
2.11 The complete file with included alphabet files
3   A more complicated complete example
3.1 Trigger to not yet replaced or replaced characters
3.2 Code of the complete example
3.3 Included fst files of the complete example
3.4 The results
4   An example using double stems
4.1 The .lex files
4.2 The complete file phon_le.fst
4.3 Run results
5   Memory considerations for rules
6   Guesser
7   Error handling (under and overdefinition)
8   Syntax checker
9   Links

The facts of the Hungarian nouns:[szerkesztés]

Conjugation[szerkesztés]

Hungarian nouns can have several suffices over 3 levels. Levels mean in this context, that suffices of a certain level can be followed by suffices of another level, in this case level 1 suffices can be followed by level 2 suffices, and these can be followed by level 3 suffices. Only one suffix of the same level can occur once in a valid Hungarian noun.

The first level of suffixes is:

  • plural
  • Possessive endings (my, your, etc...)
  • familiar endings (ék)

In a valid noun either plural, or possessive ending or familiar ending can occur; they can never occur together in the same word.

The second level of suffixes is:

  • genitive (object of owner)

The third, level, conjugation suffices correspond to prefixes in English (in, to, etc...). We will use their latin names here, like accusativ, dativ, essiv, inessiv, etc.... We use in the text the word "case" for conjugation suffices.

There are several suffices, that can only join to nominal nouns, the soc, dis, tem and ess type suffices.

In a valid noun only one conjugation suffix can occur; more than one can never occur together in the same word.

A complete transducer for the above facts looks:

$CASEP$ = (($plu$? | $poss$? | $fam$?) $gen$? $case$) | $soc$ | $dis$ | $tem$ | $ess$

($plu$? | $poss$? |$fam$? ) means, that on the first level there may be plural, possessive or familiar suffix. The ? means, that none of these is compulsory. The | means, that only one of these three ending types can be on a valid Hungarian noun.

(..) $gen$? $case$ means, that the noun can optionally own something. Finally comes the conjugation suffix (if any), that corresponds to the prepositions in English.

$soc$ | $dis$ | $tem$ | $ess$ are third level, the conjugation suffices, that make only sense if hanged onto a singular nominal noun. Only one of them can be used at a time.

 
Some examples:
rém-ek-nek
noun-plural-dat

rém-eim-et
noun-poss1p-acc

rém-eid-é-nek
noun-poss2p-gens-dat

rém-estül
noun-soc

Vowel harmony[szerkesztés]

Hungarian conjugation uses vowel harmony. Vowel harmony is based on, that vowels can be BackVowels like aáéoóuú or FrontVowels, like eéiíöőüű. FrontVowels again can be FrontVowelRounded like öőüű and FrontVowelUnrounded like eéií.

Conjugation endings can have two elements, like ban/ben, one of them FrontVowel, the other BackVowel. If a noun's last syllable contains a BackVowel, the BackVowel affix will be used, otherwise the FrontVowel one.

If a conjugation ending has 3 forms, like on/en/ön, then there are always two FrontVowel endings there, one of them FrontVowelRounded (ön), the other FrontVowelUnrounded (en). Again depending on the last syllable Vowel, the fitting ending must be used.

Assimilating conjugation affices[szerkesztés]

In the example below the assimilating suffices vá/vé (fac) and val/vel (ins) will be used. They are assimilating, because they are used as follows:

if the word ends with vowel, their first letter is v, for example: né-vé né-vel
if the word ends with consonant, the v becomes identical with the ending consonant
for example: nék-kel ném-mel

First example[szerkesztés]


In the example below, assimilating suffices are realized using the agreement variables of SFST.

Let us consider a simplified conjugation program that conjugates two nouns: né and tar.

Symbols[szerkesztés]

First we define the symbols we will use:


#cons# = bcdfghjklmnprstvwxyz
#vowel# = aeiouáéíówúöüőű
#letter# = #cons##vowel#
#FrontVowel# = eéiíöőüű
#FrontVowelUnrounded# = eéií
#BackVowel# = aáouóú
#BackVowel1# = ouóú
#FrontVowelRounded# = öüőű
#marker# = <cins><cfac><cnom><cplur><cgens><cposss1><dup>

Markers are handy, if we want to see in case of a certain suffix, what kind of other suffices are used before a certain suffix.

Rules[szerkesztés]

In the second step we define the rules, we want to have applied to each word. Rules handle vowel harmony.


% First substitute variable, <AA> will be given value here
ALPHABET = [#cons#] [#vowel#] <Noun> <dup> <ins> <fac> \
	 <AAA> <oeoez> [#marker#]  <VV> <OEOE> <OEOE1> <AA>:[ea]
$ma0$ =  ([#BackVowel#] [#cons#]* <Noun> .*) <AA> <=>  a

Each rule must be preceded by an alphabet, that defines the used symbolic variables, and the one that we want to have substituted by this rule.

The second... sixth rule:


% Second substitute variable, <AAA> will be given value here
ALPHABET = [#cons#] [#vowel#] <Noun> <dup> <ins> <fac> \
         <oeoez> [#marker#] <VV> <OEOE> <OEOE1> <AAA>:[éá]
$ma1$ =  ([#BackVowel#] [#cons#]* <Noun> .*) <AAA> <=>  á 

% Third substitute variable, <oeoez> will be given value here
ALPHABET = [#cons#] [#vowel#] <Noun> <dup> <ins> <fac> \
         <VV> <OEOE> <OEOE1> [#marker#] <oeoez>:[oeö<>]
$As2$ =  ([#BackVowel#] [#cons#]+ <Noun> .*) <oeoez> <=>  o 
$As3$ =  ([#FrontVowelRounded#] [#cons#]+ <Noun> .*) <oeoez> <=>  ö 
$As4$ =  ([#FrontVowelUnrounded#] [#cons#]+ <Noun> .*) <oeoez> <=>  e 

$ma2$ = ($As2$ & $As3$ & $As4$) 

% Fourth substitute variable, <OEOE> will be given value here
ALPHABET = [#cons#] [#vowel#] <Noun> <dup> <ins> <fac> \
         <VV> <OEOE1> [#marker#] <OEOE>:[oeö]
$oeoe1$ =  ([#BackVowel#] [#cons#]* <Noun> .*) <OEOE> <=>  o 
$oeoe2$ = ([#FrontVowelUnrounded#] [#cons#]* <Noun> .*) <OEOE> <=>  e 
$rp1$ = $oeoe1$ &  $oeoe2$  

% Fifth substitute variable, <OEOE1> will be given value here
ALPHABET = [#cons#] [#vowel#] <Noun> <dup> <ins> <fac> \
         <VV> [#marker#] <OEOE1>:[oeö<>]
$oeoe11$ =  ([#BackVowel#] [#cons#]+ <Noun> .*) <OEOE1> <=>  o 
$oeoe12$ = ([#FrontVowelUnrounded#] [#cons#]+ <Noun> .*) <OEOE1> <=>  e 
$oeoe13$ = ([#FrontVowelRounded#] [#cons#]+ <Noun> .*) <OEOE1> <=>  ö 
$rp2$ = $oeoe11$ &  $oeoe12$  & $oeoe13$

% Sixth substitute variable, <VV> will be given value here
ALPHABET = [#cons#] [#vowel#] <Noun> <dup> <ins> <fac> [#marker#] \
	 <VV>:[v<>]
$rp3$ = (([#vowel#]<Noun>[^#cons#]*) | (<Noun>[#vowel#][^#cons#]*)| (<Noun>.*[#vowel#][^#cons#]*) <dup> .*)  <VV> <=>  v % tarévá, lévé

Usage of agreement variables for assimilating affices


We use an agreement variable for the assimilating rules val/vel and vá/vé:


% Using agreement value for duplicating of consonant for vá/vé/val/vel endings
#=D# = #cons#
$T$ = {[#=D#]}:{[#=D#][#=D#]}
ALPHABET = [#cons#] [#vowel#] <Noun> <fac> <dup><ins> [#marker#]
% tar-> tarrá
$duplicate1$ = $T$ ^-> ( __ <Noun> [^#letter#]* <dup> .*)
% tarok -> tarokká
$duplicate2$ = $T$ ^-> ( <Noun>  .* __ [^#vowel#]* <dup> .*)

Transformation of ending a end e[szerkesztés]


Finally the rule to transform word ending e to é and a to á, if there are affixes behind it:


% a to á and e to é if word ends with a or e
$a_to_aa$ = {a}:{á} ^-> (__ [<Noun>] [^k].*)
$e_to_ee$ = {e}:{é} ^-> (__ [<Noun>] [^k].*)

POS tag deletion[szerkesztés]


and we delete the pos tags and markers, after all finished:


% delete pos tags
ALPHABET = [#cons#] [#vowel#] [#marker#<Noun>]:<>
$delete_POS$ =  .*

Tiny inflection logic[szerkesztés]


The simplified inflection part looks:


%%%%%%%%%%%%%%%%% inflections%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% A tiny subset of Hungarian inflection to show the principle %
% <Noun> is needed to see the word''s end
$plu$ = <pl>:{<cplur><oeoez>k}

$nom$ =  <nom>:{<cnom>}
$ins$ =  <ins>:{<cins><dup><VV><AA>l}
$fac$ =  <fac>:{<cfac><dup><VV><AAA>} 

$case$ =  $fac$ | $ins$ | $nom$
$posss1$ =  {<posss1>}:{<cposss1><OEOE1>m} 
$poss$ =  $posss1$ 
$gen$ =  {<cgens><gen>}:{é} 
$gen$ =  $gen$ 

% (ház-aknak ház-amnak ház-ak-é(i)nak ház-am-é(i)nak ház-nak) 
$CASEP$ = ($plu$?  | $poss$?) $gen$? $case$

Lexicon read in and applying of the rules sequentially


We read in the words to be conjugated from a file


$morph$ = "noun-reg001.lex" <Noun>

Apply the inflection rules onto them and check them


$morph$ = $morph$ $CASEP$
$morph$ >> "morph1.a"   % Test if all case suffixes there

Now we apply all the rules we put together in the first part. By applying sequentially we save memory, and it compiles fast.


$morph$ = "noun-reg001.lex" <Noun>
$morph$ = $morph$ $CASEP$
$morph$ >> "morph1.a"   % Test if all case suffixes there
$morph$ = $morph$ || $ma0$
$morph$ = $morph$ || $ma1$
$morph$ = $morph$ || $ma2$
$morph$ = $morph$ || $rp1$
$morph$ = $morph$ || $rp2$
$morph$ = $morph$ || $rp3$
$morph$ = $morph$ || $duplicate1$
$morph$ = $morph$ || $duplicate2$
$morph$ = $morph$ || $a_to_aa$
$morph$ = $morph$ || $e_to_ee$
$morph$ = $morph$ || $delete_POS$
$morph$

Results[szerkesztés]

We can check the results by using fst-generate, on the left side the conjugated noun, on the right side the stem and the grammar applied.

fst-generate -b raggenpl22.a 
 né	né<Noun><nom>
 tar	tar<Noun><nom> 
 néé	né<Noun><cgens><gen><nom> 
 ném	né<Noun><posss1><nom> 
 nék	né<Noun><pl><nom> 
 névé	né<Noun><fac> 
 tarrá	tar<Noun><fac> 
 taré	tar<Noun><cgens><gen><nom> 
 nével	né<Noun><ins> 
 tarral	tar<Noun><ins> 
 tarom	tar<Noun><posss1><nom> 
 tarok	tar<Noun><pl><nom> 
 néévé	né<Noun><cgens><gen><fac> 
 némé	né<Noun><posss1><cgens><gen><nom> 
 némmé	né<Noun><posss1><fac> 
 néké	né<Noun><pl><cgens><gen><nom> 
 nékké	né<Noun><pl><fac> 
 tarévá	tar<Noun><cgens><gen><fac> 
 néével	né<Noun><cgens><gen><ins> 
 némmel	né<Noun><posss1><ins> 
 nékkel	né<Noun><pl><ins> 
 taréval	tar<Noun><cgens><gen><ins> 
 taromé	tar<Noun><posss1><cgens><gen><nom> 
 tarommá	tar<Noun><posss1><fac> 
 taroké	tar<Noun><pl><cgens><gen><nom> 
 tarokká	tar<Noun><pl><fac> 
 némévé	né<Noun><posss1><cgens><gen><fac> 
 nékévé	né<Noun><pl><cgens><gen><fac> 
 tarommal	tar<Noun><posss1><ins> 
 tarokkal	tar<Noun><pl><ins> 
 némével	né<Noun><posss1><cgens><gen><ins> 
 nékével	né<Noun><pl><cgens><gen><ins> 
 taromévá	tar<Noun><posss1><cgens><gen><fac> 
 tarokévá	tar<Noun><pl><cgens><gen><fac> 
 taroméval	tar<Noun><posss1><cgens><gen><ins> 
 tarokéval	tar<Noun><pl><cgens><gen><ins>

The complete fst file in one piece:[szerkesztés]


%%%%%%%%%%%%%% raggenpl22.fst %%%%%%%%%%%%%%%%%%%    
% http://wiki.prog.hu/wiki/SFST_magyar_főnévragozás vá-vé-val-vel
%%%%%%%%%%%%%% Hungarian nouns vá,vé, val, vel endings (case: ins, fac)  %%%%%%%%%%%
% ins val, vel
% fac vá, vé
%%% words
% tar
% né
%%%% rule
% tar-rá
% tar-om-má
% né-vé
% tar-é-vá
% tar-ok-ká
% nék-ké
% né-é-vé
% ....
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Vocal harmony is solved by using FrontVowel and
% BackVowel susbtitution variables
%%%%%%%%%%%%%%% symbols %%%%%%%%%%%%%%%%%%%%%%
#cons# = bcdfghjklmnprstvwxyz
#vowel# = aeiouáéíówúöüőű
#letter# = #cons##vowel#
#FrontVowel# = eéiíöőüű
#FrontVowelUnrounded# = eéií
#BackVowel# = aáouóú
#BackVowel1# = ouóú
#FrontVowelRounded# = öüőű
#marker# = <cins><cfac><cnom><cplur><cgens><cposss1><dup>
%%%%%%%%%%%%%%% phon rules %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Here are all substitute variables listed as an overview %%%
% they must be filled separate for each rule %%%%%%%%%%%%%%%%
% ALPHABET = [#cons#] [#vowel#] <AA>:e <AA>:a  \
%          <AAA>:é <AAA>:á \
%          <oeoez>:o <oeoez>:e <oeoez>:ö <oeoez>:<> \
%          <VV>:v <VV>:<>  \
%          <OEOE>:o <OEOE>:e <OEOE>:ö \
%          <OEOE1>:o <OEOE1>:e <OEOE1>:ö <OEOE1>:<> \
%          <Noun> <dup> <ins> <fac>
% First substitute variable, <AA> will be given value here
ALPHABET = [#cons#] [#vowel#] <Noun> <dup> <ins> <fac> \
	 <AAA> <oeoez> [#marker#]  <VV> <OEOE> <OEOE1> <AA>:[ea]
$ma0$ =  ([#BackVowel#] [#cons#]* <Noun> .*) <AA> <=>  a 

% Second substitute variable, <AAA> will be given value here
ALPHABET = [#cons#] [#vowel#] <Noun> <dup> <ins> <fac> \
         <oeoez> [#marker#] <VV> <OEOE> <OEOE1> <AAA>:[éá]
$ma1$ =  ([#BackVowel#] [#cons#]* <Noun> .*) <AAA> <=>  á 

% Third substitute variable, <oeoez> will be given value here
ALPHABET = [#cons#] [#vowel#] <Noun> <dup> <ins> <fac> \
         <VV> <OEOE> <OEOE1> [#marker#] <oeoez>:[oeö<>]
$As2$ =  ([#BackVowel#] [#cons#]+ <Noun> .*) <oeoez> <=>  o 
$As3$ =  ([#FrontVowelRounded#] [#cons#]+ <Noun> .*) <oeoez> <=>  ö 
$As4$ =  ([#FrontVowelUnrounded#] [#cons#]+ <Noun> .*) <oeoez> <=>  e 

$ma2$ = ($As2$ & $As3$ & $As4$) 

% Fourth substitute variable, <OEOE> will be given value here
ALPHABET = [#cons#] [#vowel#] <Noun> <dup> <ins> <fac> \
         <VV> <OEOE1> [#marker#] <OEOE>:[oeö]
$oeoe1$ =  ([#BackVowel#] [#cons#]* <Noun> .*) <OEOE> <=>  o 
$oeoe2$ = ([#FrontVowelUnrounded#] [#cons#]* <Noun> .*) <OEOE> <=>  e 
$rp1$ = $oeoe1$ &  $oeoe2$  

% Fifth substitute variable, <OEOE1> will be given value here
ALPHABET = [#cons#] [#vowel#] <Noun> <dup> <ins> <fac> \
         <VV> [#marker#] <OEOE1>:[oeö<>]
$oeoe11$ =  ([#BackVowel#] [#cons#]+ <Noun> .*) <OEOE1> <=>  o 
$oeoe12$ = ([#FrontVowelUnrounded#] [#cons#]+ <Noun> .*) <OEOE1> <=>  e 
$oeoe13$ = ([#FrontVowelRounded#] [#cons#]+ <Noun> .*) <OEOE1> <=>  ö 
$rp2$ = $oeoe11$ &  $oeoe12$  & $oeoe13$

% Sixth substitute variable, <VV> will be given value here
ALPHABET = [#cons#] [#vowel#] <Noun> <dup> <ins> <fac> [#marker#] \
	 <VV>:[v<>]
$rp3$ = (([#vowel#]<Noun>[^#cons#]*) | (<Noun>[#vowel#][^#cons#]*)| (<Noun>.*[#vowel#][^#cons#]*) <dup> .*)  <VV> <=>  v % tarévá, lévé

% Using agreement value for duplicating of consonant for vá/vé/val/vel endings
#=D# = #cons#
$T$ = {[#=D#]}:{[#=D#][#=D#]}
ALPHABET = [#cons#] [#vowel#] <Noun> <fac> <dup><ins> [#marker#]
% tar-> tarrá
$duplicate1$ = $T$ ^-> ( __ <Noun> [^#letter#]* <dup> .*)
% tarok -> tarokká
$duplicate2$ = $T$ ^-> ( <Noun>  .* __ [^#vowel#]* <dup> .*)

% a to á and e to é if word ends with a or e
$a_to_aa$ = {a}:{á} ^-> (__ [<Noun>] [^k].*)
$e_to_ee$ = {e}:{é} ^-> (__ [<Noun>] [^k].*)
% delete pos tags
ALPHABET = [#cons#] [#vowel#] [#marker#<Noun>]:<>
$delete_POS$ =  .*

%%%%%%%%%%%%%%%%%% inflections%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% A tiny subset of Hungarian inflection to show the principle %
% <Noun> is needed to see the word''s end
$plu$ = <pl>:{<cplur><oeoez>k}

$nom$ =  <nom>:{<cnom>}
$ins$ =  <ins>:{<cins><dup><VV><AA>l}
$fac$ =  <fac>:{<cfac><dup><VV><AAA>} 

$case$ =  $fac$ | $ins$ | $nom$
$posss1$ =  {<posss1>}:{<cposss1><OEOE1>m} 
$poss$ =  $posss1$ 
$gen$ =  {<cgens><gen>}:{é} 
$gen$ =  $gen$ 

% (ház-aknak ház-amnak ház-ak-é(i)nak ház-am-é(i)nak ház-nak) 
$CASEP$ = ($plu$?  | $poss$?) $gen$? $case$

%%%%%%%%%%%%%%%%%%%%%%% HU morphology for nouns%%%%%%%%%%%%%%%%%%
%%% This is a highly memory effective and fast compiling %%%%%%%%
%%% solution by subsequently applying the rules to the words %%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$morph$ = "noun-reg001.lex" <Noun>
$morph$ = $morph$ $CASEP$
$morph$ >> "morph1.a"   % Test if all case suffixes there
$morph$ = $morph$ || $ma0$
$morph$ = $morph$ || $ma1$
$morph$ = $morph$ || $ma2$
$morph$ = $morph$ || $rp1$
$morph$ = $morph$ || $rp2$
$morph$ = $morph$ || $rp3$
$morph$ = $morph$ || $duplicate1$
$morph$ = $morph$ || $duplicate2$
$morph$ = $morph$ || $a_to_aa$
$morph$ = $morph$ || $e_to_ee$
$morph$ = $morph$ || $delete_POS$
$morph$

%%%%%%%%%%% noun-reg001.lex %%%%%%%%%%%%%%%%%%%%
% tar
% né
%%%%%%%%%% fst-generate -b raggenpl2.a  %%%%%%%%%%%%%
% né	né<Noun><nom>
% tar	tar<Noun><nom> 
% néé	né<Noun><cgens><gen><nom> 
...
% taroméval	tar<Noun><posss1><cgens><gen><ins> 
% tarokéval	tar<Noun><pl><cgens><gen><ins> 
%%%%%% do.sh%%%%%%%%%
% fst-compiler-utf8 raggenpl2.fst raggenpl2.a
% fst-generate morph8.a >/tmp/morph8
% ...

Keeping the alphabet apart[szerkesztés]

To keep the above file more readable, the alphabet part can be kept apart in little files, and included into the file like:

file alph1.fst:


ALPHABET = [#cons#] [#vowel#] <Noun> <dup> <ins> <fac> \
 <AAA> <oeoez> <VV> <OEOE> <OEOE1> \

inclusion of file alph1.fst:


% First substitute variable, <AA> will be given value here
#include "alph1.fst"   <AA>:[ea]
$ma0$ =  ([#BackVowel#] [#cons#]* <Noun> .*) <AA> <=>  a

The complete file with included alphabet files[szerkesztés]


%%%%%%%%%%%%%% raggenpl2.fst %%%%%%%%%%%%%%%%%%%
% http://wiki.prog.hu/wiki/SFST_magyar_főnévragozás vá-vé-val-vel
%%%%%%%%%%%%%% Hungarian nouns vá,vé, val, vel endings (case: ins, fac)  %%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Vocal harmony is solved by using FrontVowel and
% BackVowel susbtitution variables
%%%%%%%%%%%%%%% symbols %%%%%%%%%%%%%%%%%%%%%%
#cons# = bcdfghjklmnprstvwxyz
#vowel# = aeiouáéíówúöüőű
#letter# = #cons##vowel#
#FrontVowel# = eéiíöőüű
#FrontVowelUnrounded# = eéií
#BackVowel# = aáouóú
#BackVowel1# = ouóú
#FrontVowelRounded# = öüőű
%%%%%%%%%%%%%%% phon rules %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Here are all substitute variables listed as an overview %%%
% they must be filled separate for each rule %%%%%%%%%%%%%%%%
% ALPHABET = [#cons#] [#vowel#] <AA>:e <AA>:a  \
%          <AAA>:é <AAA>:á \
%          <oeoez>:o <oeoez>:e <oeoez>:ö <oeoez>:<> \
%          <VV>:v <VV>:<>  \
%          <OEOE>:o <OEOE>:e <OEOE>:ö \
%          <OEOE1>:o <OEOE1>:e <OEOE1>:ö <OEOE1>:<> \
%          <Noun> <dup> <ins> <fac>
% First substitute variable, <AA> will be given value here
#include "alph1.fst"   <AA>:[ea]
$ma0$ =  ([#BackVowel#] [#cons#]* <Noun> .*) <AA> <=>  a 

% Second substitute variable, <AAA> will be given value here
#include "alph2.fst"  <AAA>:[éá]
$ma1$ =  ([#BackVowel#] [#cons#]* <Noun> .*) <AAA> <=>  á 

% Third substitute variable, <oeoez> will be given value here
#include "alph3.fst"  <oeoez>:[oeö<>]
$As2$ =  ([#BackVowel#] [#cons#]+ <Noun> .*) <oeoez> <=>  o 
$As3$ =  ([#FrontVowelRounded#] [#cons#]+ <Noun> .*) <oeoez> <=>  ö 
$As4$ =  ([#FrontVowelUnrounded#] [#cons#]+ <Noun> .*) <oeoez> <=>  e 

$ma2$ = ($As2$ & $As3$ & $As4$) 

% Fourth substitute variable, <OEOE> will be given value here
#include "alph4.fst" <OEOE>:[oeö]
$oeoe1$ =  ([#BackVowel#] [#cons#]* <Noun> .*) <OEOE> <=>  o 
$oeoe2$ = ([#FrontVowelUnrounded#] [#cons#]* <Noun> .*) <OEOE> <=>  e 
$rp1$ = $oeoe1$ &  $oeoe2$  

% Fifth substitute variable, <OEOE1> will be given value here
#include "alph5.fst" <OEOE1>:[oeö<>]
$oeoe11$ =  ([#BackVowel#] [#cons#]+ <Noun> .*) <OEOE1> <=>  o 
$oeoe12$ = ([#FrontVowelUnrounded#] [#cons#]+ <Noun> .*) <OEOE1> <=>  e 
$oeoe13$ = ([#FrontVowelRounded#] [#cons#]+ <Noun> .*) <OEOE1> <=>  ö 
$rp2$ = $oeoe11$ &  $oeoe12$  & $oeoe13$

% Sixth substitute variable, <VV> will be given value here
#include "alph6.fst" <VV>:[v<>]
$rp3$ = (([#vowel#]<Noun>[^#cons#]*) | (<Noun>[#vowel#][^#cons#]*)| (<Noun>.*[#vowel#][^#cons#]*) <dup> .*)  <VV> <=>  v % tarévá, lévé

% Using agreement value for duplicating of consonant for vá/vé/val/vel endings
#=D# = #cons#
$T$ = {[#=D#]}:{[#=D#][#=D#]}
ALPHABET = [#cons#] [#vowel#] <Noun> <fac> <dup><ins>
% tar-> tarrá
$duplicate1$ = $T$ ^-> ( __ <Noun> [^#letter#]* <dup> .*)
% tarok -> tarokká
$duplicate2$ = $T$ ^-> ( <Noun>  .* __ [^#vowel#]* <dup> .*)

% a to á and e to é if word ends with a or e
$a_to_aa$ = {a}:{á} ^-> (__ [<Noun>] [^k].*)
$e_to_ee$ = {e}:{é} ^-> (__ [<Noun>] [^k].*)
% delete pos tags
ALPHABET = [#cons#] [#vowel#] [<Noun><dup>]:<>
$delete_POS$ =  .*

%%%%%%%%%%%%%%%%%% inflections%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% A tiny subset of Hungarian inflection to show the principle %
% <Noun> is needed to see the word''s end
$plu$ = <pl>:{<oeoez>k}

$nom$ =  <nom>:{}
$ins$ =  <ins>:{<dup><VV><AA>l}
$fac$ =  <fac>:{<dup><VV><AAA>} 

$case$ =  $fac$ | $ins$ | $nom$
$posss1$ =  {<posss1>}:{<OEOE1>m} 
$poss$ =  $posss1$ 
$gen$ =  {<gen>}:{é} 
$gen$ =  $gen$ 

% (ház-aknak ház-amnak ház-ak-é(i)nak ház-am-é(i)nak ház-nak) 
$CASEP$ = ($plu$?  | $poss$?) $gen$? $case$

%%%%%%%%%%%%%%%%%%%%%%% HU morphology for nouns%%%%%%%%%%%%%%%%%%
%%% This is a highly memory effective and fast compiling %%%%%%%%
%%% solution by subsequently applying the rules to the words %%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$morph$ = "noun-reg001.lex" <Noun>
$morph$ = $morph$ $CASEP$
$morph$ >> "morph1.a"   % Test if all case suffixes there
$morph$ = $morph$ || $ma0$
$morph$ = $morph$ || $ma1$
$morph$ = $morph$ || $ma2$
$morph$ = $morph$ || $rp1$
$morph$ = $morph$ || $rp2$
$morph$ = $morph$ || $rp3$
$morph$ = $morph$ || $duplicate1$
$morph$ = $morph$ || $duplicate2$
$morph$ = $morph$ || $a_to_aa$
$morph$ = $morph$ || $e_to_ee$
$morph$ = $morph$ || $delete_POS$
$morph$

%%%%%%%%%%% noun-reg001.lex %%%%%%%%%%%%%%%%%%%%
% tar
% né
%%%%%%%%%% fst-generate reggenpl2.a | interpret1.pl %%%%%%%%%%%%%
% né  sav:'<Noun><nom>' 
% tar  sav:'<Noun><nom>' 
...
% taroméval  sav:'<Noun><posss1><gen><ins>' 
% tarokéval  sav:'<Noun><pl><gen><ins>' 
%%%%%% do.sh%%%%%%%%%
% fst-compiler-utf8 raggenpl2.fst raggenpl2.a
% fst-generate morph8.a >/tmp/morph8
% ...

file alph1.fst-------------------------
ALPHABET = [#cons#] [#vowel#] <Noun> <dup> <ins> <fac> \
 <AAA> <oeoez> <VV> <OEOE> <OEOE1> \

file alph2.fst-------------------------
ALPHABET = [#cons#] [#vowel#] <Noun> <dup> <ins> <fac> \
         <oeoez> <VV> <OEOE> <OEOE1> \

file alph3.fst-------------------------
ALPHABET = [#cons#] [#vowel#] <Noun> <dup> <ins> <fac> \
         <VV> <OEOE> <OEOE1>

file alph4.fst-------------------------
ALPHABET = [#cons#] [#vowel#] <Noun> <dup> <ins> <fac> \
         <VV>  <OEOE1>

file alph5.fst-------------------------
ALPHABET = [#cons#] [#vowel#] <Noun> <dup> <ins> <fac> \
         <VV>

file alph6.fst-------------------------
ALPHABET = [#cons#] [#vowel#] <Noun> <dup> <ins> <fac> \

A more complicated complete example[szerkesztés]

A little bit more complicated file with all suffixes, using the principles listed above. The conjugated words are:


 
pehely
kehely
virágkehely
zabpehely
hópehely
kehely
kukoricapehely
pehely

The words are irregular ones having ephenthesis. That means, that for example plural of pehely is pelyhek, of kehely kelyhek. poss1 (my pehely) is pelyhem, for plural and the soc and sup cases, <soc><sup><acc><pl>#tpos#, where #tpos# means al poss cases, and is realized by the transducer $hely$.

In this example some variables, like <AA> <AAA> <plv> ... <UUE1> can only have one value. Since here is no condition, they get their value in the step

$phonpehely$ = $phonpehely$ || $ma0$

Their value is only set in the first ALPHABET definition, it is not necessary, to set their values in the further ALPHABET-s.

Trigger to not yet replaced or replaced characters[szerkesztés]

In the replacement operation:

$oeoez1$ =  (([#ei##oeue#] <Noun>[^#cons#]* [<csup>] .*)| \
             (<Noun>.*[#vowel#<AE1>]:.+[^#cons#]* [<csup>] .*)| \
            ([#cons#] <Noun>.*[#vowel#<AE1>]:.+[^#cons#]* [<csup>] .*)) <oeoez> <=>  <>

the code uses the notation [<variable name>]:. That notation makes it possible to trigger to not yet replaced variables, that have their symbolic value, in the example <AE1>. It is not yet replaced with any character, therefore [#vowel#] would not trigger to that character, but [#vowel#<AE1>]:. does. (after the closing bracket there must be a colon and a dot, like ]:.). If a character is already replaced at check time, the [#vowel#] or [#cons#] suffices for triggering.

Code of the complete example[szerkesztés]

%%%%%%%%%%%%%%%%%%%%%%% phon_pehely.fst magas pehely  %%%%%%%%%%%%%%%%
#include "symbols1.fst"

ALPHABET = [#cons#] [#vowel#] \
         <AA>:e  \  % nak, nek, ba, be, ban, ben, 
         <AAA>:é  \ % vá, vé, nál, nél
         <plv>:<> \ % füvek
         <plv1>:<> \ % füvek
         <plv2>:<> \ % füvek
         <plv3>:<> \ % füvek
         <plvp>:<> \ % füvek
         <plvs>:<> \ % füvek
         <uue>:ü \ % ul, ül
         <oooe>:ő \ % tól, től. ból, ből, ról. ről
         <oeoe>  \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <J>:<>  <JP>:<> \
         <OEOE2>:e  \ % etek, otok, ötök (2-nd vowel)
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <AE> <AE1>:e <AE1>:é \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1>:ü \   % juk, jük
         <Noun> [#marker#]

$ma0$ = (<Noun>.*[<tpos3>].*) <AE1> <=> é ((.*[#scase#].*) |\
             ([#gen#].*[<cnom><cfor>] .*)) %lovából, cfor 

ALPHABET = [#cons#] [#vowel#] \
         <AA> \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <uue> \ % ul, ül
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>:e <oeoe>:ö  \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <J>  <JP> \
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <AE> <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]

$ma4$ =  ([#oeue##ei#] [#cons#]* <Noun>.*[<UUE><UUE1>#oeue#]:.[^#vowel#]:.*[<csup><call>].*) <oeoe> <=>  ö 
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <uue> \ % ul, ül
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>  \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <J>  <JP> \
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <VV>  \ % val, vel, vá, vé
         <EOA>:e <EOA>:<> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <AE> <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]

$ma6$ =  (([#ei#] [#cons#]* <Noun>.*[#cons#<plv><plv1>]:.[^#letter#]*[<csoc>].*) |\
([#ei#] [#cons#]+ <Noun>[<csoc>].*)) <EOA> <=>  e 

% This would blow up a 3.2 GB machine 
%$ma0$ = ($ma0$ || $ma4$ || $ma6$ ) 

ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <uue> \ % ul, ül
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>  \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <J>  <JP> \
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE>:e <OEOE>:ö \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <AE> <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]

$rp1$ = ([#ei#] [#cons#]* <Noun> [^<UUE1>]:.*) <OEOE> <=>  e 
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <uue> \ % ul, ül
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>  \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <J>  <JP> \
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1>:e <OEOE1>:ö <OEOE1>:<> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <AE> <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$oeoe12$ = ([#ei#] [#cons#]+ <Noun> .*) <OEOE1> <=>  e 
$oeoe13$ = ([#oeue#] [#cons#]+ <Noun> .*) <OEOE1> <=>  ö 
$rp2$ =  $oeoe12$  & $oeoe13$
%           ([#magas#]<Noun>[#tposp#].*)) <JP> <=>  <> 
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <uue> \ % ul, ül
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>  \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <J>  <JP> \
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <AE>:e <AE>:<>  <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]

$rp41$ = ([#magas#]<Noun>[#tposp#].*) <AE> <=>  <> 
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <uue> \ % ul, ül
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>  \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <J>  <JP> \
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <AE> <AE1> \ % ja, je, a, e
         <UUE>:ü <UUE>:<> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$rp5$ =  ([#magas#] [#cons#]+ <Noun> .*) <UUE> <=>  ü
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <uue> \ % ul, ül
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>  \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <J>  <JP> \
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <VV>:v <VV>:<>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <AE> <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$vv4$ = ((<Noun>.*[#vowel#<AE1>]:.+[^#cons#]*[<dup>] .*) | ([#vowel#] <Noun>[^#vowel#]*[<dup>] .*))  <VV> <=>  v % tarévá, lévé
$rp7$ = $vv4$ 
% must be the last,because checks for vowel and cons in between <Noun> and [<te><cacc>]
% needs modification because after r for example there is no vowel necessary
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <uue> \ % ul, ül
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>  \ % hoz, hez, höz, 
         <oeoez1>:e  <oeoez1>:<> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <J>  <JP> \
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <AE> <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$rp8$ =  (([#ei#] [#cons#]+ <Noun>[^#vowel#]* <tpl> .*)| \
           ([#ei#] [#cons#]* <Noun>.*[#cons#]+[^#vowel#]*<tpl> .*)) <oeoez1> <=>  e 

ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <uue> \ % ul, ül
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>  \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2>:e  <oeoez2>:<> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <J>  <JP> \
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <AE> <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$rp9$ =  (([#ei#] [#cons#]+ <Noun>[^#vowel#]* [<cacc>] .*)| \
           ([#ei#] [#cons#]* <Noun>.*[#cons#]+[^#vowel#]*[<cacc>] .*)) <oeoez2> <=>  e 

ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <uue> \ % ul, ül
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>  \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>:e  <oeoez3>:<>  \ % onként, enként, önként
         <J>  <JP> \
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <AE> <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$rp10$ =  (([#ei#] [#cons#]+ <Noun>[^#vowel#]* [<cdis>] .*)| \
           ([#ei#] [#cons#]* <Noun>.*[#cons#]+[^#vowel#]*[<cdis>] .*)) <oeoez3> <=>  e 

ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv>:<> \ % füvek
         <plv1>:<> \ % füvek
         <plv2>:<> \ % füvek
         <plv3>:<> \ % füvek
         <plvp>:<> \ % füvek
         <plvs>:<> \ % füvek
         <uue> \ % ul, ül
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>  \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez>:e <oeoez>:ö <oeoez>:<> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <J>  <JP> \
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <AE> <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$oeoez1$ =  (([#ei##oeue#] <Noun>[^#cons#]* [<csup>] .*)| \
             (<Noun>.*[#vowel#<AE1>]:.+[^#cons#]* [<csup>] .*)| \
            ([#cons#] <Noun>.*[#vowel#<AE1>]:.+[^#cons#]* [<csup>] .*)) <oeoez> <=>  <> 
$oeoez2$ =  ([#oeue##ei#] [#cons#]* <Noun>.*[<UUE1><UUE>#oeue#]:.[^#vowel#]:.*[<csup><call>].*) <oeoez> <=>  ö 
$rp11$ = $oeoez1$ & $oeoez2$ 

% This would blow up a 3.2 GB machine 
%$rp$ = ($rp1$ || $rp2$ || $rp41$ || $rp5$ || $rp7$ || $rp8$ || $rp9$ || $rp10$ || $rp11$ ) 

#include "vave.fst"

ALPHABET = [#cons#] [#vowel#] <Noun> [#marker#][#letter#][#gen#]<dup>

% tar-> tarrá
$duplicate1$ = ( $T1$ | $T2$ | $T3$  ) ^-> ( __ <Noun> [^#letter#]* <dup> .*)
% tarok -> tarokká
$duplicate2$ = $T$ ^-> ( <Noun> .*__ [^#letter#]* <dup> .*)

% a to á and e to é if word ends with a or e
$hely$ = ({hely}:{lyh} | {her}:{rh}) ^-> (__[<Noun>][<csoc><csup><cacc><tpl>#tpos#].*)
% delete pos tags
ALPHABET = [#cons#] [#vowel#] [<Noun>#marker#]:<>
$delete-POS$ =  .*

#include "ninfl1.fst"

% This would blow up a 3.2 GB machine 
%$ma$ = $ma0$ || $rp$
%$phon1$ = $duplicate1$ ||  $duplicate2$ || $hely$ || $delete-POS$

$phonpehely$ = "lex/noun/noun-pehely.lex" <Noun> $CASEP$ 
$phonpehely$ >> "phon/noun/phon_pehely01.a"
% This would blow up a 3.2 GB machine 
%$phonpehely$ = $phonpehely$ || $ma$ || $phon1$
$phonpehely$ = $phonpehely$ || $ma0$
$phonpehely$ = $phonpehely$ || $ma4$
$phonpehely$ = $phonpehely$ || $ma6$
$phonpehely$ = $phonpehely$ || $rp1$
$phonpehely$ = $phonpehely$ || $rp2$
$phonpehely$ = $phonpehely$ || $rp41$
$phonpehely$ = $phonpehely$ || $rp5$
$phonpehely$ = $phonpehely$ || $rp7$
$phonpehely$ = $phonpehely$ || $rp8$
$phonpehely$ = $phonpehely$ || $rp9$
$phonpehely$ = $phonpehely$ || $rp10$
$phonpehely$ = $phonpehely$ || $rp11$
$phonpehely$ = $phonpehely$ || $duplicate1$ ||  $duplicate2$ || $hely$ || $delete-POS$

$phonpehely$

Included fst files of the complete example[szerkesztés]

The included fst-s:


%%%%%%%%%%%%%%% symbols1.fst %%%%%%%%%%%%%%%%%%%%
#cons# = bcdfghjklmnprstvwxyz
#vowel# = aeiouáéíóúöüőű
#letter# = #cons##vowel#
#magas# = eéiíöőüű
#ei# = eéií
#mely# = aáouóú
#ou# = ouóú
#oeue# = öüőű
#aa# = aá
#magasito# = #ei#<oeoez1><OEOE1><AE1>
#svowel# = <oeoez1><oooe><oeoez><oeoez2><oeoez3><oeoe><uue><AA><AAA><AE><AE1><EOA><OOEE><OEOE><OEOE1><UUE1>
#cons1# = lgnt  % w/o y
#cons2# = cz  % w/o y and s (cs, zs)
#cons3# = s  % w/o y and z (sz)
#cons_r# = bcdfghjklmnpstvwxyz  % w/o r
% for jaje-ae
#plosiv# = bdghpt
#nonplosiv# = cjlrsvz
%%%%%%%%%%%%%%%%% postags%%%%%%%%%%%%%%%%%%%
#pos# = <Noun><Verb><Adj><Num>

#Digit# = 0123456789
#Perc# = \%
#Nsep# = \.\, 
#Apos# = \'
#Punct# = \.\?\!\:\,\;

% surface symbols
#Ssym# = #cons##vowel##Digit##Punct##Perc##Nsep##Apos#
#case# = <cabl><cacc><cade><call><ccau><cdat><cdel>\
         <cdis><cela><cess><cfac><cfor><cill><cine>\
         <cine1><cins><csoc><csub><csup><ctem><cter><cfam><cnom>
% nincs cfor sem cfam scase-ben, lovaként, de lovából
#scase# = <cabl><cacc><cade><call><ccau><cdat><cdel>\
         <cela><cess><cfac><cill><cine>\
         <cins><csub><csup><cter>

#tpos# = <tpos1><tpos2><tpos3><tpos4><tpos5><tpos6><tpos7><tpos8><tpos9><tpos10><tpos11><tpos12>
#tposp# = <tpos7><tpos8><tpos9><tpos10><tpos11><tpos12>
#gen# = <cgens><cgenpl>
#marker# = <dup><tpl>#gen##tpos##case#

The inflection file contains all used Hungarian conjugation affixes. It also contains possession suffixes for singular and plural, and genitive for singular and plural.


%%%%%%%%%%%%%%%%%%%%%%% ninfl1.fst %%%%%%%%%%%%%%%%
%#include "symbols1.fst" 

$plu$ = <pl>:{<tpl><plvp><oeoez1>k}

$fam$ = <fam>:{<cfam>ék}

$abl$ =  <abl>:{<cabl>t<oooe>l}               % tól, től
$acc$ =  <acc>:{<cacc><plv><oeoez2>t}         % ot, et, öt
$ade$ =  <ade>:{<cade>n<AAA>l}                % nál, nél
$all$ =  <all>:{<call>h<oeoe>z}               % hoz, hez, höz
$cau$ =  <cau>:{<ccau>ért}                    % ért
$dat$ =  <dat>:{<cdat>n<AA>k}                 % nak, nek
$del$ =  <del>:{<cdel>r<oooe>l}               % ról, ről
$dis$ =  <dis>:{<cdis><plv3><oeoez3>nként}    % onként, enként, önként naponta
$ela$ =  <ela>:{<cela>b<oooe>l}               % ból, ből
$ess$ =  <ess>:{<cess><uue>l}                 % ul, ül
$fac$ =  <fac>:{<cfac><dup><VV><AAA>}         % vá, vé
$for$ =  <for>:{<cfor>ként}                   % ként  képp, képpen
$ill$ =  <ill>:{<cill>b<AA>}                  % ba, be
$ine$ =  <ine>:{<cine>b<AA>n}                 % ban, ben
$ine1$ = <ine1>:{<cine1><OOEE>tt}             % Győrött Pécsett Kolozsvárott
$ins$ =  <ins>:{<cins><dup><VV><AA>l}         % val, vel
$nom$ =  <nom>:{<cnom>}
$soc$ =  <soc>:{<csoc><plv1><EOA>st<uue>l}    % ostul, estül, östül
$sub$ =  <sub>:{<csub>r<AA>}                  % ra, re
$sup$ =  <sup>:{<csup><plv2><oeoez>n}         % on, en, ön
$tem$ =  <tem>:{<ctem>kor}                    % kor
$ter$ =  <ter>:{<cter>ig}                     % ig

$case$ = $nom$ | $dat$ | $acc$ | $ill$ | $ine$ | $ela$ | $all$ | $ade$ |\
         $abl$ | $sup$ | $del$ | $ter$ | $for$ |\
         $cau$ | $fac$ |  $ins$ | $sub$

$posss1$ =  {<posss1>}:{<tpos1><plvs><OEOE1>m}            % om, em, öm
$posss2$ =  {<posss2>}:{<tpos2><plvs><OEOE1>d}            % od, ed, öd
$posss3$ =  {<posss3>}:{<tpos3><plvs><J><AE1>}            % ja, je
$possp1$ =  {<possp1>}:{<tpos4><plvs><UUE>nk}             % unk, ünk
$possp2$ =  {<possp2>}:{<tpos5><plvs><OEOE1>t<OEOE>k}     % otok, etek, ötök
$possp3$ =  {<possp3>}:{<tpos6><plvs><J><UUE1>k}          % juk, jük
$posss1p$ =  {<posss1p>}:{<tpos7><plvs><JP><AE>im}         % jaim
$posss2p$ =  {<posss2p>}:{<tpos8><plvs><JP><AE>id}         % jaid
$posss3p$ =  {<posss3p>}:{<tpos9><plvs><JP><AE>i}          % jai
$possp1p$ =  {<possp1p>}:{<tpos10><plvs><JP><AE>ink}       % jaink
$possp2p$ =  {<possp2p>}:{<tpos11><plvs><JP><AE>it<OEOE2>k} % jaitok jeitek for göb <OEOE2>
$possp3p$ =  {<possp3p>}:{<tpos12><plvs><JP><AE>ik}        % jaik
            

$poss$ =  $posss1$ | $posss2$ | $posss3$ | $possp1$ | $possp2$ | $possp3$ |\
         $posss1p$ | $posss2p$ | $posss3p$ | $possp1p$ | $possp2p$ | $possp3p$

$gens$ =  {<gens>}:{<cgens>é} 
$genpl$ =  {<genpl>}:{<cgenpl>éi} 

$gen$ =  $gens$ | $genpl$ 

% (ház-aknak ház-amnak ház-ak-é(i)nak ház-am-é(i)nak ház-ék-éi-nak ház-nak) 
%$CASEP$ = ($plu$?  | $poss$? ) $gen$? $case$
$CASEP$ = (($plu$?  | $poss$? | $fam$?) $gen$? $case$) | $soc$ | $dis$ | $tem$ | $ess$

%%%%%%%%%%%%%%%%%%%%%%% vave.fst %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#=D# = #cons#
$T$ = {[#=D#]}:{[#=D#][#=D#]} 
#=D# = #cons1#
$T1$ = {[#=D#]}:{[#=D#][#=D#]} y
#=D# = #cons2#
$T2$ = {[#=D#]}:{[#=D#][#=D#]} s
#=D# = #cons3#
$T3$ = {[#=D#]}:{[#=D#][#=D#]} z

The results[szerkesztés]


...
pelyhen pehely<Noun><sup>
pelyhet pehely<Noun><acc>
pehelyé pehely<Noun><gens><nom>
pehelyig        pehely<Noun><ter>
...
kehelyül        kehely<Noun><ess>
kehellyé        kehely<Noun><fac>
hópehely        hópehely<Noun><nom>
zabpehely       zabpehely<Noun><nom>
pelyhei pehely<Noun><posss3p><nom>
pelyhük pehely<Noun><possp3><nom>
pelyhén pehely<Noun><posss3><sup>
..
pehelyén        pehely<Noun><gens><sup>
pehelyét        pehely<Noun><gens><acc>
pehelykor       pehely<Noun><tem>
pehelyben       pehely<Noun><ine>
pehelyből       pehely<Noun><ela>
...
pehelytől       pehely<Noun><abl>
pehelyék        pehely<Noun><fam><nom>
pehellyel       pehely<Noun><ins>
kelyhei kehely<Noun><posss3p><nom>
kelyhük kehely<Noun><possp3><nom>
kelyhén kehely<Noun><posss3><sup>
...
kelyhemet       kehely<Noun><posss1><acc>
kelyhestül      kehely<Noun><soc>
...
kelyhekre       kehely<Noun><pl><sub>
kelyhekbe       kehely<Noun><pl><ill>
...

An other example using double stems[szerkesztés]


Some Hungarian words, like lé, ló, szülő conjugate in certain cases for historical reasons, as if they had an other stem. We show here an example to handle such word using the double stem technology SFST offers. The word lé builds in accusativ, plural and all poss cases the conjugated forms as if it had the word 'lev' as stem. However, the conjugated forms using the stem 'lé' are also acceptable. (for example: plural lék or levek)

Therefore we conjugate first lé completely. In the second part, we conjugate pseudo stem lev based on the stem 'lé' only in plural and possession mode, using acc, soc dis and conjugation suffices.

The .lex files[szerkesztés]


There are two lex files for this example. lex/noun/noun-lev.lex looks:

lé 
citromlé
gyümölcslé
...
trágyalé

and for the pseudo stem, lev looks:

lé:e<>:v
citromlé:e<>:v
gyümölcslé:e<>:v
(...)

where lé:e<>:v is the instruction for SFST, how to transform lé into lev (leave l alone, then transform first é into e and then nothing (<>) into v)

An other example for double stems is the word szülő. If we want to use the pseudo stem szül, we write szülő:<> in the lexc file. If we want to use the pseudo stem szüle, we write szülő:e into the lexc file.

The include files (symbols.fst, vave.fst and ninfl1.fst) are identical to the files listed above.

The complete file phon_le.fst[szerkesztés]


The complete fst file, phon_le.fst for double stemming looks:


%%%%%%%%%%%%%%%%%%%%%% lé like rege %%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%% phon_le.fst magas lé  %%%%%%%%%%%%%%%%%
%%%%% To save memory, first generate lé and then lev, or together transducers %%%%
#include "symbols1.fst"
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt, o
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP>  \
         <AE>  <AE1>:e <AE1>:é \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]

$ma0$ = (<Noun>.*[<tpos3>].*) <AE1> <=> é ((.*[#scase#].*) |\
             ([#gen#].*[<cnom><cfor>] .*)) %lovából, cfor 
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>:e <oeoe>:ö    \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt, o
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP>  \
         <AE> <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$ma4$ =  ([#oeue##ei#] [#cons#]* <Noun>.*[<JP><J>]:.+[<UUE><UUE1>#oeue#]:.[^#vowel#]:.*[<csup><call>].*) <oeoe> <=>  ö 
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt, o
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV>  \ % val, vel, vá, vé
         <EOA>:e <EOA>:<>  \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP>  \
         <AE> <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$ma6$ =  (([#ei#] [#cons#]* <Noun>.*[#cons#<plv><plv1>]:.[^#letter#]*[<csoc>].*) |\
([#ei#] [#cons#]+ <Noun>[<csoc>].*)) <EOA> <=>  e 

%$ma0$ = ($ma0$ & $ma4$ & $ma6$) 

ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt, o
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE>:e <OEOE>:ö  \ % etek, otok, ötök (2-nd vowel)
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP>  \
         <AE> <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$rp1$ = ([#ei#] [#cons#]* <Noun> [^<UUE1>]:.*) <OEOE> <=>  e 
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt, o
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <OEOE1>:e <OEOE1>:ö <OEOE1>:<> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP>  \
         <AE> <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$oeoe12$ = ([#ei#] [#cons#]+ <Noun> .*) <OEOE1> <=>  e 
$oeoe13$ = ([#oeue#] [#cons#]+ <Noun> .*) <OEOE1> <=>  ö 
$rp2$ =  $oeoe12$  & $oeoe13$
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt, o
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J>:j <J>:<>  <JP>  \
         <AE> <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$rp3$ =  ([#cons#]+ <Noun> .*) <J> <=>  <> 
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt, o
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP>  \
         <AE> <AE1> \ % ja, je, a, e
         <UUE>:ü <UUE>:<> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$rp5$ =  ([#magas#] [#cons#]+ <Noun> .*) <UUE> <=>  ü
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt, o
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV>:v <VV>:<> \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP>  \
         <AE> <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$rp7$ = ((<Noun>.*[#vowel#<AE1>]:.+[^#cons#]*[<dup>] .*) | ([#vowel#] <Noun>[^#vowel#]*[<dup>] .*))  <VV> <=>  v % tarévá, lévé
% must be the last,because checks for vowel and cons in between <Noun> and [<te><cacc>]
% needs modification because after r for example there is no vowel necessary
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1>:e  <oeoez1>:<> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt, o
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP>  \
         <AE> <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$rp8$ =  (([#ei#] [#cons#]+ <Noun>[^#vowel#]* <tpl> .*)| \
           ([#ei#] [#cons#]* <Noun>.*[#cons#]+[^#vowel#]*<tpl> .*)) <oeoez1> <=>  e 

ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2>:e  <oeoez2>:<> \ % at, ot, et, öt, o
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP>  \
         <AE> <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$rp9$ =  (([#ei#] [#cons#]+ <Noun>[^#vowel#]* [<cacc>] .*)| \
           ([#ei#] [#cons#]* <Noun>.*[#cons#]+[^#vowel#]*[<cacc>] .*)) <oeoez2> <=>  e 

ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt, o
         <oeoez3>:e  <oeoez3>:<>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP>  \
         <AE> <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$rp10$ =  (([#ei#] [#cons#]+ <Noun>[^#vowel#]* [<cdis>] .*)| \
           ([#ei#] [#cons#]* <Noun>.*[#cons#]+[^#vowel#]*[<cdis>] .*)) <oeoez3> <=>  e 

ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez>:e <oeoez>:ö <oeoez>:<>  \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt, o
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE2>  \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP>  \
         <AE> <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$oeoez1$ =  (([#ei##oeue#] <Noun>[^#cons#]* [<csup>] .*)| \
             (<Noun>.*[#vowel#<AE1>]:.+[^#cons#]* [<csup>] .*)| \
            ([#cons#] <Noun>.*[#vowel#<AE1>]:.+[^#cons#]* [<csup>] .*)) <oeoez> <=>  <> 
$oeoez2$ =  ([#oeue##ei#] [#cons#]* <Noun>.*[<JP><J>]:.+[<UUE1><UUE>#oeue#]:.[^#vowel#]:.*[<csup><call>].*) <oeoez> <=>  ö 
$rp11$ = $oeoez1$ & $oeoez2$ 

%$rp$ = ($rp1$ & $rp2$ & $rp3$ & $rp5$ & $rp7$ & $rp8$ & $rp9$ & $rp10$ & $rp11$ ) 

#include "vave.fst"

ALPHABET = [#cons#] [#vowel#] <Noun> [#marker#][#letter#][#gen#]<dup>

% tar-> tarrá
$duplicate1$ = ($T1$ | $T2$ | $T3$ | $T$ ) ^-> ( __ <Noun> [^#letter#]* <dup> .*)
% tarok -> tarokká
$duplicate2$ = $T$ ^-> ( <Noun> .*__ [^#letter#]* <dup> .*)

%  e to é if word ends with  e
%ALPHABET = [#cons#] [#vowel#] <Verb><Noun><Noun> [#marker#] 
$e-to-ee$ = {e}:{é} ^-> (__ [<Noun>] [^k<cfor><ctem><cnom>].*)
% delete pos tags
ALPHABET = [#cons#] [#vowel#] [<Noun>#marker#]:<>
$delete-POS$ =  .*

#include "ninfl1.fst"

%$ma$ = $ma0$ & $rp$

$phon1$ = $duplicate1$ ||  $duplicate2$ ||  $e-to-ee$ || $delete-POS$

$phonle1$ = "lex/noun/noun-le.lex" <Noun> 
$phonle1$ = $phonle1$ $CASEP$ 
$phonle1$ >> "phon/noun/hon_le01.a"
$phonle1$ = $phonle1$ || $ma0$ 
$phonle1$ = $phonle1$ || $ma4$ 
$phonle1$ = $phonle1$ || $ma6$ 
$phonle1$ = $phonle1$ || $rp1$ 
$phonle1$ = $phonle1$ || $rp2$ 
$phonle1$ = $phonle1$ || $rp3$ 
$phonle1$ = $phonle1$ || $rp5$ 
$phonle1$ = $phonle1$ || $rp7$ 
$phonle1$ = $phonle1$ || $rp8$ 
$phonle1$ = $phonle1$ || $rp9$ 
$phonle1$ = $phonle1$ || $rp10$ 
$phonle1$ = $phonle1$ || $rp11$ 
$phonle1$ = $phonle1$ || $phon1$ 
%$phonle1$ = $phonle1$ || $ma$ || $phon1$

%%%%%%%%%%%%%%%%%%%%%%% generate lev like vész %%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%% phon_lev.fst magas lev  %%%%%%%%%%%%%%%%
%#include "symbols1.fst"

ALPHABET = [#cons#] [#vowel#] \
         <AA>:e  \  % nak, nek, ba, be, ban, ben, 
         <AAA>:é  \ % vá, vé, nál, nél
         <plv>:<> \ % füvek
         <plv1>:<> \ % füvek
         <plv2>:<> \ % füvek
         <plv3>:<> \ % füvek
         <plvp>:<> \ % füvek
         <plvs>:<> \ % füvek
         <oooe>:ő \ % tól, től. ból, ből, ról. ről
         <oeoe>  \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <uue>:ü \ % ul, ül
         <VV>  \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP> \
         <AE>  <AE1>:e <AE1>:é \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1>:ü \   % juk, jük
         <Noun> [#marker#]

$ma0$ = (<Noun>.*[<tpos3>].*) <AE1> <=> é ((.*[#scase#].*) |\
             ([#gen#].*[<cnom><cfor>] .*)) %lovából, cfor 
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>:e <oeoe>:ö    \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV> \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP> \
         <AE>  <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$ma4$ =  ([#oeue##ei#] [#cons#]* <Noun>.*[<UUE><UUE1>#oeue#]:.[^#vowel#]:.*[<csup><call>].*) <oeoe> <=>  ö 
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV> \ % val, vel, vá, vé
         <EOA>:e <EOA>:<> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP> \
         <AE>  <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$ma6$ =  (([#ei#] [#cons#]* <Noun>.*[#cons#<plv><plv1>]:.[^#letter#]*[<csoc>].*) |\
([#ei#] [#cons#]+ <Noun>[<csoc>].*)) <EOA> <=>  e 


%$ma0$ = ($ma0$ & $ma4$ & $ma6$ ) 

ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV> \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE>:e <OEOE>:ö \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP> \
         <AE>  <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$rp1$ = ([#ei#] [#cons#]* <Noun> [^<UUE1>]:.*) <OEOE> <=>  e 
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV> \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1>:e <OEOE1>:ö <OEOE1>:<> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP> \
         <AE>  <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$oeoe12$ = ([#ei#] [#cons#]+ <Noun> .*) <OEOE1> <=>  e 
$oeoe13$ = ([#oeue#] [#cons#]+ <Noun> .*) <OEOE1> <=>  ö 
$rp2$ =  $oeoe12$  & $oeoe13$
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV> \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J>:j <J>:<> <JP> \
         <AE>  <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$rp3$ =  ([#cons#]+ <Noun> .*) <J> <=>  <> 
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV> \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <JP>:j <JP>:<> <J> \
         <AE>  <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$rp4$ =  (([#cons#]+ <Noun> .*) |\
           ([#magas#]<Noun>[#tposp#].*)) <JP> <=>  <> 
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV> \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP> \
         <AE>:e <AE>:<>  <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$rp41$ = ([#magas#]<Noun>[#tposp#].*) <AE> <=>  <> 
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV> \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP> \
         <AE>  <AE1> \ % ja, je, a, e
         <UUE>:ü <UUE>:<>  \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$rp5$ =  ([#magas#] [#cons#]+ <Noun> .*) <UUE> <=>  ü
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV>:v <VV>:<> \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP> \
         <AE>  <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$vv4$ = ((<Noun>.*[#vowel#<AE1>]:.+[^#cons#]*[<dup>] .*) | ([#vowel#] <Noun>[^#vowel#]*[<dup>] .*))  <VV> <=>  v % tarévá, lévé
$rp7$ = $vv4$ 
% must be the last,because checks for vowel and cons in between <Noun> and [<te><cacc>]
% needs modification because after r for example there is no vowel necessary
ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1>:e  <oeoez1>:<> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV> \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP> \
         <AE>  <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$rp8$ =  (([#ei#] [#cons#]+ <Noun>[^#vowel#]* <tpl> .*)| \
           ([#ei#] [#cons#]* <Noun>.*[#cons#]+[^#vowel#]*<tpl> .*)) <oeoez1> <=>  e 
% vészt és nem vészet!!

ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2>:e  <oeoez2>:<> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV> \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP> \
         <AE>  <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$rp9$ =  ([#ei#] [#cons#]+ <Noun>(.*[#cons#]+[^#vowel#]*[<cacc>] .*| [<cacc>].* )) <oeoez2> <=>  e 

ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>:e  <oeoez3>:<>   \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV> \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP> \
         <AE>  <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$rp10$ =  (([#ei#] [#cons#]+ <Noun>[^#vowel#]* [<cdis>] .*)| \
           ([#ei#] [#cons#]* <Noun>.*[#cons#]+[^#vowel#]*[<cdis>] .*)) <oeoez3> <=>  e 

ALPHABET = [#cons#] [#vowel#] \
         <AA>  \  % nak, nek, ba, be, ban, ben, 
         <AAA>  \ % vá, vé, nál, nél
         <plv> \ % füvek
         <plv1> \ % füvek
         <plv2> \ % füvek
         <plv3> \ % füvek
         <plvp> \ % füvek
         <plvs> \ % füvek
         <oooe> \ % tól, től. ból, ből, ról. ről
         <oeoe>   \ % hoz, hez, höz, 
         <oeoez1> \ % ok, ek, ök
         <oeoez>:e <oeoez>:ö <oeoez>:<> \ %  on, en, ön, 
         <oeoez2> \ % at, ot, et, öt
         <oeoez3>  \ % onként, enként, önként
         <uue> \ % ul, ül
         <VV> \ % val, vel, vá, vé
         <EOA> \ % estül, ostul., östül
         <OEOE> \ % etek, otok, ötök (2-nd vowel)
         <OEOE1> \ % om, od, otok, (1st vowel) jeitek (last vowel)
         <J> <JP> \
         <AE>  <AE1> \ % ja, je, a, e
         <UUE> \ % unk, ünk
         <UUE1> \   % juk, jük
         <Noun> [#marker#]
$oeoez1$ =  (([#ei##oeue#] <Noun>[^#cons#]* [<csup>] .*)| \
             (<Noun>.*[#vowel#<AE1>]:.+[^#cons#]* [<csup>] .*)| \
            ([#cons#] <Noun>.*[#vowel#<AE1>]:.+[^#cons#]* [<csup>] .*)) <oeoez> <=>  <> 
$oeoez2$ =  ([#oeue##ei#] [#cons#]* <Noun>.*[<UUE1><UUE>#oeue#]:.[^#vowel#]:.*[<csup><call>].*) <oeoez> <=>  ö 
$rp11$ = $oeoez1$ & $oeoez2$ 

%$rp$ = ($rp1$ & $rp2$ & $rp3$ & $rp4$ & $rp41$ & $rp5$ & $rp7$ & $rp8$ & $rp9$  & $rp10$ & $rp11$ ) 

#=D# = #cons#
$T$ = {[#=D#]}:{[#=D#][#=D#]} 
#=D# = #cons1#
$T1$ = {[#=D#]}:{[#=D#][#=D#]} y
#=D# = #cons2#
$T2$ = {[#=D#]}:{[#=D#][#=D#]} s
#=D# = #cons3#
$T3$ = {[#=D#]}:{[#=D#][#=D#]} z
ALPHABET = [#cons#] [#vowel#] <Noun> [#marker#][#letter#][#gen#]<dup>

% tar-> tarrá
$duplicate1$ = ($T$ | $T1$ | $T2$ | $T3$ ) ^-> ( __ <Noun> [^#letter#]* <dup> .*)
% tarok -> tarokká
$duplicate2$ = $T$ ^-> ( <Noun> .*__ [^#letter#]* <dup> .*)

% a to á and e to é if word ends with a or e
%ALPHABET = [#cons#] [#vowel#] <Verb><Noun> [#marker#] 
%$a-to-aa$ = {a}:{á} ^-> (__ [<Noun>] [^k].*)
%$e-to-ee$ = {e}:{é} ^-> (__ [<Noun>] [^k].*)
% delete pos tags
ALPHABET = [#cons#] [#vowel#] [<Verb><Noun><Adj>#marker#]:<>
$delete-POS$ =  .*

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%#include "ninfl1.fst"
$CASEP1$ = ($plu$ $gen$? $case$) | ($poss$ $gen$? $case$) | $acc$ | $soc$ | $dis$ 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%$ma$ = $ma0$ & $rp$

$phon1$ = $duplicate1$ ||  $duplicate2$ ||  $delete-POS$

$phonlev$ = "lex/noun/noun-lev.lex" <Noun> $CASEP1$ 
$phonlev$ >> "phon/noun/phon_lev01.a"
$phonlev$ = $phonlev$ || $ma0$ 
$phonlev$ = $phonlev$ || $ma4$ 
$phonlev$ = $phonlev$ || $ma6$ 
$phonlev$ = $phonlev$ || $rp1$ 
$phonlev$ = $phonlev$ || $rp2$ 
$phonlev$ = $phonlev$ || $rp3$ 
$phonlev$ = $phonlev$ || $rp4$ 
$phonlev$ = $phonlev$ || $rp41$ 
$phonlev$ = $phonlev$ || $rp5$ 
$phonlev$ = $phonlev$ || $rp7$ 
$phonlev$ = $phonlev$ || $rp8$ 
$phonlev$ = $phonlev$ || $rp9$ 
$phonlev$ = $phonlev$ || $rp10$ 
$phonlev$ = $phonlev$ || $rp11$ 
$phonlev$ = $phonlev$ || $phon1$ 
%$phonlev$ = $phonlev$ || $ma$ || $phon1$

%%%%%%%%%%%%%%% 'or' together lé and lev transducers %%%%%%%%%%%%%
$phonlev$ | $phonle1$

Run results[szerkesztés]


Some results of the double stemming file's run:

 
lé	lé<Noun><nom>
sólé	sólé<Noun><nom>
léé	lé<Noun><gens><nom>
léig	lé<Noun><ter>
hólé	hólé<Noun><nom>
ivólé	ivólé<Noun><nom>
...
lééi	lé<Noun><genpl><nom>
lékor	lé<Noun><tem>
léért	lé<Noun><cau>
léhez	lé<Noun><all>
léék	lé<Noun><fam><nom>
leve	lé<Noun><posss3><nom>
levet	lé<Noun><acc>
húslé	húslé<Noun><nom>
almalé	almalé<Noun><nom>
sóléé	sólé<Noun><gens><nom>
sóléig	sólé<Noun><ter>
lééig	lé<Noun><gens><ter>
léként	lé<Noun><for>
levei	lé<Noun><posss3p><nom>
levük	lé<Noun><possp3><nom>
levén	lé<Noun><posss3><sup>
levét	lé<Noun><posss3><acc>
leved	lé<Noun><posss2><nom>
levem	lé<Noun><posss1><nom>
levek	lé<Noun><pl><nom>
...

Memory considerations for rules.[szerkesztés]


Approaches that do not work.

Why the complication with ALPHABET/1 rule at a time, why not ALPHABET/many rules? Because this saves memory.

Let's consider the following approach (version 1):

ALPHABET= ... <AA>:[abc] VV:[def]
$rule01$ = (condition1) AA <=> a
$rule02$ = (condition2) AA <=> b
$rule11$ = (condition3) VV <=> d
$rule12$ = (condition4) VV <=> e
$rule$ = $rule01$ & $rule02$ & $rule00$ & $rule12$
...
$morph$ = "words.lex" <Noun>
$morph$ = $morph$ $CASEP$
$morph = $morph || $rule$
...

The above approach would work fine for a few rules, but it would use over 3 GB memory for about 12 rules, and also would take several minutes to compile, and therefore it is practically unapplicable.

Also this approach would not work in practical life (version 2):

ALPHABET= ... <AA>:[abc] VV
$rule01$ = (condition1) AA <=> a
$rule02$ = (condition2) AA <=> b
$rule1$ = ($rule01$ & $rule02$)
ALPHABET= ... <AA> VV:[def]
$rule11$ = (condition3) VV <=> d
$rule12$ = (condition4) VV <=> e
$rule2$ =  ($rule00$ & $rule12$)
...
$rule = $rule1$ || $rule2$

$morph$ = "words.lex" <Noun>
$morph$ = $morph$ $CASEP$
$morph = $morph || $rule$
...

We see the same behaviour with this approach: memory usage increases, and also compilation time is extremely high.

We strongly recommend the approach, shown in the above examples (version 3):

 
ALPHABET= ... <AA>:[abc] VV
$rule01$ = (condition1) AA <=> a
$rule02$ = (condition2) AA <=> b
$rule1$ = ($rule01$ & $rule02$)
ALPHABET= ... <AA> VV:[def]
$rule11$ = (condition3) VV <=> d
$rule12$ = (condition4) VV <=> e
$rule2$ =  ($rule00$ & $rule12$)
...

$morph$ = "words.lex" <Noun>
$morph$ = $morph$ $CASEP$
$morph = $morph || $rule1$
$morph = $morph || $rule2$
...

This approach works with virtually no memory usage, and compilation time is very fast.

Remark: German morphology uses version 2. If German morphology uses version 3, compilation time increases from 341 seconds (5.8 minutes) to 1027 seconds (~16 minutes).

Guesser.[szerkesztés]


Guesser is a tool, that checks, if an entered string looks like a valid word. If yes, it analyzes it as a word, and passes back it's guess for the word's present grammatical form, or, the other way around, it creates required grammatical forms from regular expression defined strings. Guessers are indispensable tools for agglutinating languages, since we can not put all possible words of the world into our dictionary, but we still need to express for example, that somebody goes *into* an African river or town, whose name is not in our lexicon.

Guessers are easily built using SFST by using regular expressions instead of, or besides reading lexicons.

Let us consider only the line of raggenpl22.fst, our first example program:


$morph$ = "noun-reg001.lex" <Noun>

If we add to this line the above mentioned regular expression string capability:


$morph$ = "noun-reg001.lex" <Noun> | ([#cons#]*[#vowel#]+|[#cons#*#vowel#+#cons#+#vowel#]*)  <Noun>

and then compile the fst file, we have built in the guessing capability.

Some testing examples:

           
fst-mor raggenpl22.a
reading transducer...
finished.
analyze> abbas
abbas<Noun><nom>
analyze> őz
őz<Noun><nom>
analyze> a
analyze> 
analyze> 
generate> abas<Noun><nom>
abas
generate> abas<Noun><fac>
abassá
generate> abas<Noun><ins>
abassal
generate>

If you know, that the language you are working with does not have in any valid word having more than 4 consonants and 3 vowels subsequentially, then you can tell this using:

$Cons$ = [#cons#]
$Vowel$ = [#vowel#]
$Cons0-4$ = $Cons$? $Cons$? $Cons$? $Cons$? 
$Cons1-4$ = $Cons$ $Cons$? $Cons$? $Cons$? 
$Vowel0-3$ = $Vowel$? $Vowel$? $Vowel$? 
$Vowel1-3$ = $Vowel$ $Vowel$? $Vowel$?  
$morph$ = "noun-reg001.lex" <Noun> | ($Cons0-4$ $Vowel1-3$ | ($Cons0-4$ $Vowel1-3$ $Cons1-4$ $Vowel0-3$)*)  <Noun>

In this case you will get at testing:

fst-mor raggenpl22.a
reading transducer...
finished.
analyze> abbbba
abbbba<Noun><nom>
analyze> abbbbba
no result for abbbbba
analyze> baaab
baaab<Noun><nom>
analyze> baaaab
no result for baaaab
analyze>

Error handling (over and underdefinition)[szerkesztés]


Underdefinition[szerkesztés]


It can happen, that a rule, intended or not, gets under or overdefined. It is underdefined, if the user simply forgot to write it, but a virtual variable is defined, for example:

ALPHABET = ... <VV>:[v<>] <AA>:[ae]
$rule1$ = (condition1) AA<=> a
...
$morph$ = $morph$ || $rule1$

In this case, word<VV><AA> will become wordva and worda in the output list.

Overdefinition[szerkesztés]


If a rule is overdefined, for example like:

ALPHABET = ... <VV>:[v<>] <AA>:[ae]
$rule1$ = (condition1) <AA><=> a
$rule2$ = (condition1) <AA> <=> e
...
$morph$ = $morph$ || $rule1$
$morph$ = $morph$ || $rule2$

In this case, word will not appear in the output if it contains <AA>. If for example <AA> pertains to case dativ, dativ will not appear in the output.

Syntax checker[szerkesztés]


Since SFST does not check *.fst file syntax very thoroughtly, there exists an additional tool, that makes a relatively thorough and strict test of the used SFST variables and their usage, for example of under and overspecification. The tool dc_check is written in perl. It can be downloaded from the same web page, where SFST can be downloaded from.

Links[szerkesztés]