In Epos, nearly all of the TTS processing is controlled by a rule file;
there is one rule file per language and it usually has the .rul
suffix. The rule file for the German language, for instance, resides
by default in lng/german/german.rul. The rules may also slightly
vary for the individual voices using the
soft options.
The text being processed by Epos is internally stored in a multi-level data
structure suitable for the application of transformational rules. Every phonetic
unit (or an approximation of one) is represented by a single node in the
structure. The nodes are organized into layers corresponding to linguistic
levels of description, such that a unit of level n can list its
immediate constituents, that is units of level n-1. Every layer
also has a symbolic name, which is used to refer to it in the rules.
The number and symbolic names of individual levels can be specified
with the unit_levels option before the languages are defined.
An example is given in a table.
| Level name | written TSR semantics | spoken TSR semantics |
text | the whole text | the whole text |
sent | sentence construction | terminated utterance |
colon | sentence/clause/colon | intonational unit |
word | word | stress unit |
syll | word | syllable |
phone | letter | sound |
segment | segment | |
Every unit, be it segmental level or not, may contain a character. The TSR, as generated by the text parser, contains the appropriate punctuation at suprasegmental levels (that is, levels above the phone level): spaces at the word level, commas at the intonational unit level, periods, question marks and such will become the contents of a sentence (terminated utterance) level. Some suprasegmental units will have no content, because they have been delimited only implicitly; for example, a colon-final word has been delimited by a comma, but the comma is actually a colon level symbol: the last word will have no content. This content may be modified by the rules and actually, it often is. This allows marking up a unit for a later use (changing its content into an arbitrary character, such as a digit or anything else, then applying some rules only within units having this contents using a rule of type inside.)
The rules are applied sequentially, unless stated otherwise. Each rule operates units of a certain level within a unit of some other level; for instance, a rule may assimilate phones within a word, another rule may change the syllabic prosody within a colon. The smaller units being manipulated are called target units, the larger unit is referred to as a scope unit; the respective levels are called scope and target. Each scope unit is always processed separately (from any other scope units) as if no other text ever existed. For example, if the scope of some assimilation happens to be "word", every word will have the rule applied in isolation and the assimilation will never apply across the word boundary nor will be able to distiguish a word boundary from sentence boundary.
Any line of the rules file may contain at most one rule and possibly some comment. The rule begins with an operation code specifier (what to do), followed by the parameter (one word, opcode specific), and possibly by scope and target specification, if the defaults (usually word and phone, respectively) are not suitable.
The scope and the target can be one of the
available levels of linguistic description as defined
with the unit_levels option. If target or even scope
for a rule is not specified, the default_target or
default_scope option value, respectively, will be used.
The typical defaults are phone and word, respectively.
Every rule is evaluated within certain unit, and the scope specifies, what kind of unit it should be. The meaning of the target is somewhat opcode specific, but generally, this is the level which is affected by that rule, or the lowest level affected by that rule within the scope. See the individual rule descriptions in this section in conjunction with the real world rule files for exact interpretation of the target level.
The code, scope and target identifier is not case sensitive, but the parameter usually is.
As you sometimes need different character encodings for different languages, there is this mechanism for switching character encodings in text files including rule files and dictionaries.
You can use the backslash to escape any special character including the backslash itself anywhere in the rules just as in the configuration files. See the corresponding section for details.
Notice especially the possibility of referring to several internal pseudocharacters with the nice property that they can never be found in the input text and therefore are suitable for temporary markers of all kinds in the rules. See the raise rule example.
In addition, special characters listed in the table of escape sequences can be inserted using the same mechanism.
@include Directive
Any text starting with a semicolon or # not in the middle of a word up to the
end of the line is a comment. It will be properly ignored. If a line
doesn't contain anything except whitespace and/or comment, it is also
ignored. The @include directive can be used to nest the rule
files. The same rules apply within .ini files; for more
details, see
the @include directive in configuration files.
A line which doesn't contain a rule may contain a macro definition instead.
It is specified as identifier = replacement, for example,
$vowel = aeiouy
Alternatively, the keyword external may follow an identifier instead of
the equality sign and the replacement:
$some_pathname external
This way the macro identifier is assigned the value of its corresponding configuration parameter (for the current language if possible).
The macros will get expanded anywhere where they occur except for their own
point of definition. Therefore, $vowel $short$long will be a valid macro
definition, provided that $short and $long have already been defined. The
expansion is performed at the definition time and it is not iterated, because
the replacement is not expected to contain the dollar sign.
Macros can later be redefined if you wish and they can be local to a block of rules as described below.
If there be any uncertainty concerning the exact length of the identifier,
you can use braces to delimit it: ${name} is usually equal to $name, but
$nameaeiou is not equal to ${name}aeiou. It is also possible to use
a colon or an ampersand as a delimiter: $name&aeiou.
It is a good practice to use macros extensively for classes of symbols so that the same sets and subsets of characters are listed only once in the rules and therefore are kept consistent throughout. The exact values of the macros are however always language specific and so Epos doesn't specify any built-in macros. If any macros are used in the examples for specific rules below, reasonable definitions of the macros are assumed to precede the rule.
For an abundance of examples see existing rule files.
!) Operator
Whenever an unordered list of tokens should be specified within the parameter
to some rule (use common sense and/or individual rule descriptions above),
you can also make negative specifications, such as "all consonants except
l and r". To do this, use the exclamation mark serving as an "except" operator:
$consonants!lr (The right operand is subtracted from the left one.)
If there is no left operand, say in !x, the semantics is "all but x".
A consequence is that ! alone means "everything".
The operator is right-associative; !$vowels!ou means "all excluding vowels,
but o and u don't count as vowels just now". Therefore,
o and u are included in this unordered list.
This operator never works for ordered lists, not even
for the syll rule sonority groups. But there is
a similar usage associated with rule types if, with,
prep and postp, where the exclamation mark can be
used to negate the condition; see the respective rule types.
The rule types described in this subsection operate in some way on a list of words (or other strings), which can range from a few items up to machine-generated megabytes of data. These strings are usually listed in a separate file, while the parameter of such a rule is the file name. Alternatively, the strings can be quoted inside the rule file, especially if only a few ones are listed. Such a collection of strings is called a dictionary and obeys the same format for any rule type which needs external data (except for the neural networks).
The dictionary consists of multiple lines, each of which contains a single dictionary item. An item consists of two whitespace separated words, the former being the item itself, the latter being some string associated with the item. Often, the second string is used to replace every occurrence of the first string in the text being processed. That's why the strings are called replacee and replacer, respectively. The order of dictionary items is not significant.
We use adaptive hash tables -- and balanced optionally bounded depth AVL trees for collisions -- for representation of the dictionary in memory to achieve instant lookups of any item, even in a huge dictionary.
The replacee cannot contain whitespace (unless escaped with a backslash), but the replacer can. That is, if more than two words are found on a line, the first one is the replacee and the rest of the line, except for any post-replacee and/or trailing whitespace, becomes the replacer. However, some rule types may not allow multiple word replacers.
The dictionaries follow the same conventions for character encoding, escaping special characters, inclusion directives and comments as the rule files and other text files.
Instead of a file name reference, it is possible to quote the contents of the dictionary directly; this is done by encapsulating the contents in double quotes. Dictionary items are in this case whitespace-separated, every replacer and replacee are separated by a comma.
The dictionary may either be parsed and loaded into memory at Epos startup
or at the moment of the first use. The former option's advantage is
early error reporting, while the latter can sometimes completely avoid
loading a huge unused dictionary. Use the option paranoid to choose
your preference.
subst Substring substitution. The replacers replace every occurrence of their respective replacees; longer matches are matched first; the process is iterated until no replacee occurs in the string. It there is a tie between several matches of equal length, the rightmost match is chosen.
It is required
either to have a phone target, or to keep all the replacers
and replacees the same length, because otherwise it is not obvious how to handle the
children of the units affected. Note also that to be considered a match
with the phone target, all characters other than phones also
have to match (must be found or not found on the same positions in both
the replacee and the occurrence in question) except for the terminating
scope-level separator (if any), which is invisible to this rule type.
Any replacer may begin with a ^ or end with a $. That forces the substring being replaced to be at the beginning or the end of the scope unit, respectively. This ^ or $ also counts as a character when determining the longest match.
The replacer should not contain units of the scope level or higher.
Unless the paranoid option is set, this is tolerated, but the
replacer is truncated at the first of such characters.
With the phone target, this rule type will drop the
internal structure of the replaced text as soon as a match is found.
In other words: an affected scope unit with a replacer is re-parsed as
any other plain text. With any other target the original structure
is always kept.
Infinitely looping substitutions are currently reported as an error condition.
As this rule type should not be used for trivial tasks with short and often matching dictionaries, the example we shall now give is somewhat involved:
< word syll
regress \ >m(!_!) word word
regress \ >d(!_!) word word
regress \ >t(!_!) word word
regress \ >q(!_!) word word
regress \ >p(!_!) word word
>
subst "^mmmmm,mmmxm ^mmmmmm,mmmxmm ^mmmmmmm,mmmmxmm \
pmm,pxm qmmm,qxmm pmmm,pxmm tmmmm,tmmxm qmmmm,qxmxm \
dmmmmm,dmmxmm tmmmmm,tmmxmm qmmmmm,qxmxmm pmmmmm,pxmmxm \
dmmmmmm,dmmxmmm tmmmmmm,tmmxmmm qmmmmmm,qxmmxmm \
pmmmmmm,pxmmxmm dmmmmmmm,dmmxmmxm tmmmmmmm,tmmxmmxm \
qmmmmmmm,qxmmmxmm pmmmmmmm,pxmmmxmm \
mmmmmmmm,mmmmxmmm" colon word
postp "m" word word
The purpose of this example sequence of rules is to form stress units out of graphical words, based on the following assumptions for the given language: polysyllables are retained as stress units, but following monosyllables may be merged to them; monosyllables which are colon-final should be retained; other monosyllables may merge to each other and/or to the preceding polysyllable; the merges should not produce too long stress units.
The first part of the example is used to mark all non-colon-final
(more exactly: space delimited) words with the letters m,d,t,q,p
based on the number of syllables; note that the p is used
not only for pentasyllables, but also for all words of more than five
syllables. Then the substition rule is used to relabel some
monosyllables (destined as heads of stress units consisting solely
of monosyllables) with x. Finally, all monosyllables that
haven't been relabeled to x are merged to the preceding
stress word if there is any using the postp rule.
The substitution rule in the example has 21 dictionary items,
the first three being applicable only at the colon-initial position.
Mostly it directly lists the resulting labeling for the whole
colon, but with extremely long sequences of monosyllables it
relies on the facts that the longest matching replacee (and the
rightmost one if there are multiple) is chosen and that the
substitution process is iterated. For example,
pmmmmmmmmm would be first relabeled to pmmmmmxmmm
using the last item as listed in the dictionary and then once more
using a different item to pxmmxmxmmm.
prep Preposition. If the scope unit is identical to some replacee,
it gets replaced with its respective replacer and merged to its right-hand
neighbor. If there is no such neighbor, nothing happens. As with the
subst rule, the target
must currently be phone or all the replacers of sizes corresponding
to their respective replacees.
Let us take a typical example:
prep preps.dic
where the referenced file contains a list of prepositions for the language, e.g. for Czech:
bez
do
k
ke
ku
na
nad
o
od
po
pod
pro
pRed
pRes pRez
s
u
v
ve
z
za
ze
You can see that most of the prepositions have the replacers
identical to the replacees, so that the preposition doesn't
change except for being merged to the left if found.
There is however one irregular monosyllabic preposition
in Czech which does change its behavior with regard to
the voicing assimilation in Czech, and this can be done
too as shown. Notice also that the unit
(here: the word) must match the dictionary item
exactly, as opposed to mere substring matching required
by the subst rule.
As a special case, if the parameter begins with an exclamation mark, then the rest of the parameter is parsed as usual and any substitutions are performed exactly as usual, but the scope units which get finally merged to their respective right hand neighbors are exactly those which are not found in the dictionary.
A typical example can be the following rule whose purpose is to abolish all syllable boundaries (within each word). The rule defines an empty dictionary and then merges each word which is not found in the dictionary and which has something to be merged to.
prep !"" syll
postpPostposition. See rule type prep for the description and examples, but the resultant unit is merged to its left-hand neighbor instead of the right-hand neighbor.
analyzeThis rule type analyzes a unit of level immediately below the scope level into a sequence of units based on a dictionary of known contents of the new units at the target level and priorities assigned to them. We will explain the operation of this rule in terms of the morphematic analysis, i.e. the most common use with the scope level being the word, the result of the analysis will be the morpheme level (just below the word level) and the target will be phones.
Each item of the dictionary corresponds to a single morpheme (some linguists would prefer to say "morph" here). The replacee is the form the result ofcept for any post-replacee and/or trailing whitespace, becomes the replacer. However, some rule types may not allow multiple word replacers.
The dictionaries follow the same conventions for character encoding, escaping special characters, inclusion directives and comments as the rule files and other text files.
Instead of a file name reference, it is possible to quote the contents of the dictionary directly; this is done by encapsulating the contents in double quotes. Dictionary items are in this case whitespace-separated, every replacer and replacee are separated by a comma.
The dictionary may either be parsed and loaded into memory at Epos startup
or at the moment of the first use. The former option's advantage is
early error reporting, while the latter can sometimes completely avoid
loading a huge unused dictionary. Use the option paranoid to choose
your preference.
subst Substring substitution. The replacers replace every occurrence of their respective replacees; longer matches are matched first; the process is iterated until no replacee occurs in the string. It there is a tie between several matches of equal length, the rightmost match is chosen.
It is required
either to have a phone target, or to keep all the replacers
and replacees the same length, because otherwise it is not obvious how to handle the
children of the units affected. Note also that to be considered a match
with the phone target, all characters other than phones also
have to match (must be found or not found on the same positions in both
the replacee and the occurrence in question) except for the terminating
scope-level separator (if any), which is invisible to this rule type.
Any replacer may begin with a ^ or end with a $. That forces the substring being replaced to be at the beginning or the end of the scope unit, respectively. This ^ or $ also counts as a character when determining the longest match.
The replacer should not contain units of the scope level or higher.
Unless the paranoid option is set, this is tolerated, but the
replacer is truncated at the first of such characters.
With the phone target, this rule type will drop the
internal structure of the replaced text as soon as a match is found.
In other words: an affected scope unit with a replacer is re-parsed as
any other plain text. With any other target the original structure
is always kept.
Infinitely looping substitutions are currently reported as an error condition.
As this rule type should not be used for trivial tasks with short and often matching dictionaries, the example we shall now give is somewhat involved:
< word syll
regress \ >m(!_!) word word
regress \ >d(!_!) word word
regress \ >t(!_!) word word
regress \ >q(!_!) word word
regress \ >p(!_!) word word
>
subst "^mmmmm,mmmxm ^mmmmmm,mmmxmm ^mmmmmmm,mmmmxmm \
pmm,pxm qmmm,qxmm pmmm,pxmm tmmmm,tmmxm qmmmm,qxmxm \
dmmmmm,dmmxmm tmmmmm,tmmxmm qmmmmm,qxmxmm pmmmmm,pxmmxm \
dmmmmmm,dmmxmmm tmmmmmm,tmmxmmm qmmmmmm,qxmmxmm \
pmmmmmm,pxmmxmm dmmmmmmm,dmmxmmxm tmmmmmmm,tmmxmmxm \
qmmmmmmm,qxmmmxmm pmmmmmmm,pxmmmxmm \
mmmmmmmm,mmmmxmmm" colon word
postp "m" word word
The purpose of this example sequence of rules is to form stress units out of graphical words, based on the following assumptions for the given language: polysyllables are retained as stress units, but following monosyllables may be merged to them; monosyllables which are colon-final should be retained; other monosyllables may merge to each other and/or to the preceding polysyllable; the merges should not produce too long stress units.
The first part of the example is used to mark all non-colon-final
(more exactly: space delimited) words with the letters m,d,t,q,p
based on the number of syllables; note that the p is used
not only for pentasyllables, but also for all words of more than five
syllables. Then the substition rule is used to relabel some
monosyllables (destined as heads of stress units consisting solely
of monosyllables) with x. Finally, all monosyllables that
haven't been relabeled to x are merged to the preceding
stress word if there is any using the postp rule.
The substitution rule in the example has 21 dictionary items,
the first three being applicable only at the colon-initial position.
Mostly it directly lists the resulting labeling for the whole
colon, but with extremely long sequences of monosyllables it
relies on the facts that the longest matching replacee (and the
rightmost one if there are multiple) is chosen and that the
substitution process is iterated. For example,
pmmmmmmmmm would be first relabeled to pmmmmmxmmm
using the last item as listed in the dictionary and then once more
using a different item to pxmmxmxmmm.
prep Preposition. If the scope unit is identical to some replacee,
it gets replaced with its respective replacer and merged to its right-hand
neighbor. If there is no such neighbor, nothing happens. As with the
subst rule, the target
must currently be phone or all the replacers of sizes corresponding
to their respective replacees.
Let us take a typical example:
prep preps.dic
where the referenced file contains a list of prepositions for the language, e.g. for Czech:
bez
do
k
ke
ku
na
nad
o
od
po
pod
pro
pRed
pRes pRez
s
u
v
ve
z
za
ze
You can see that most of the prepositions have the replacers
identical to the replacees, so that the preposition doesn't
change except for being merged to the left if found.
There is however one irregular monosyllabic preposition
in Czech which does change its behavior with regard to
the voicing assimilation in Czech, and this can be done
too as shown. Notice also that the unit
(here: the word) must match the dictionary item
exactly, as opposed to mere substring matching required
by the subst rule.
As a special case, if the parameter begins with an exclamation mark, then the rest of the parameter is parsed as usual and any substitutions are performed exactly as usual, but the scope units which get finally merged to their respective right hand neighbors are exactly those which are not found in the dictionary.
A typical example can be the following rule whose purpose is to abolish all syllable boundaries (within each word). The rule defines an empty dictionary and then merges each word which is not found in the dictionary and which has something to be merged to.
prep !"" syll
postpPostposition. See rule type prep for the description and examples, but the resultant unit is merged to its left-hand neighbor instead of the right-hand neighbor.
analyzeThis rule type analyzes a unit of level immediately below the scope level into a sequence of units based on a dictionary of known contents of the new units at the target level and priorities assigned to them. We will explain the operation of this rule in terms of the morphematic analysis, i.e. the most common use with the scope level being the word, the result of the analysis will be the morpheme level (just below the word level) and the target will be phones.
Each item of the dictionary corresponds to a single morpheme (some linguists would prefer to say "morph" here). The replacee is the form the result ofcept for any post-replacee and/or trailing whitespace, becomes the replacer. However, some rule types may not allow multiple word replacers.
The dictionaries follow the same conventions for character encoding, escaping special characters, inclusion directives and comments as the rule files and other text files.
Instead of a file name reference, it is possible to quote the contents of the dictionary directly; this is done by encapsulating the contents in double quotes. Dictionary items are in this case whitespace-separated, every replacer and replacee are separated by a comma.
The dictionary may either be parsed and loaded into memory at Epos startup
or at the moment of the first use. The former option's advantage is
early error reporting, while the latter can sometimes completely avoid
loading a huge unused dictionary. Use the option paranoid to choose
your preference.
subst Substring substitution. The replacers replace every occurrence of their respective replacees; longer matches are matched first; the process is iterated until no replacee occurs in the string. It there is a tie between several matches of equal length, the rightmost match is chosen.
It is required
either to have a phone target, or to keep all the replacers
and replacees the same length, because otherwise it is not obvious how to handle the
children of the units affected. Note also that to be considered a match
with the phone target, all characters other than phones also
have to match (must be found or not found on the same positions in both
the replacee and the occurrence in question) except for the terminating
scope-level separator (if any), which is invisible to this rule type.
Any replacer may begin with a ^ or end with a $. That forces the substring being replaced to be at the beginning or the end of the scope unit, respectively. This ^ or $ also counts as a character when determining the longest match.
The replacer should not contain units of the scope level or higher.
Unless the paranoid option is set, this is tolerated, but the
replacer is truncated at the first of such characters.
With the phone target, this rule type will drop the
internal structure of the replaced text as soon as a match is found.
In other words: an affected scope unit with a replacer is re-parsed as
any other plain text. With any other target the original structure
is always kept.
Infinitely looping substitutions are currently reported as an error condition.
As this rule type should not be used for trivial tasks with short and often matching dictionaries, the example we shall now give is somewhat involved:
< word syll
regress \ >m(!_!) word word
regress \ >d(!_!) word word
regress \ >t(!_!) word word
regress \ >q(!_!) word word
regress \ >p(!_!) word word
>
subst "^mmmmm,mmmxm ^mmmmmm,mmmxmm ^mmmmmmm,mmmmxmm \
pmm,pxm qmmm,qxmm pmmm,pxmm tmmmm,tmmxm qmmmm,qxmxm \
dmmmmm,dmmxmm tmmmmm,tmmxmm qmmmmm,qxmxmm pmmmmm,pxmmxm \
dmmmmmm,dmmxmmm tmmmmmm,tmmxmmm qmmmmmm,qxmmxmm \
pmmmmmm,pxmmxmm dmmmmmmm,dmmxmmxm tmmmmmmm,tmmxmmxm \
qmmmmmmm,qxmmmxmm pmmmmmmm,pxmmmxmm \
mmmmmmmm,mmmmxmmm" colon word
postp "m" word word
The purpose of this example sequence of rules is to form stress units out of graphical words, based on the following assumptions for the given language: polysyllables are retained as stress units, but following monosyllables may be merged to them; monosyllables which are colon-final should be retained; other monosyllables may merge to each other and/or to the preceding polysyllable; the merges should not produce too long stress units.
The first part of the example is used to mark all non-colon-final
(more exactly: space delimited) words with the letters m,d,t,q,p
based on the number of syllables; note that the p is used
not only for pentasyllables, but also for all words of more than five
syllables. Then the substition rule is used to relabel some
monosyllables (destined as heads of stress units consisting solely
of monosyllables) with x. Finally, all monosyllables that
haven't been relabeled to x are merged to the preceding
stress word if there is any using the postp rule.
The substitution rule in the example has 21 dictionary items,
the first three being applicable only at the colon-initial position.
Mostly it directly lists the resulting labeling for the whole
colon, but with extremely long sequences of monosyllables it
relies on the facts that the longest matching replacee (and the
rightmost one if there are multiple) is chosen and that the
substitution process is iterated. For example,
pmmmmmmmmm would be first relabeled to pmmmmmxmmm
using the last item as listed in the dictionary and then once more
using a different item to pxmmxmxmmm.
prep Preposition. If the scope unit is identical to some replacee,
it gets replaced with its respective replacer and merged to its right-hand
neighbor. If there is no such neighbor, nothing happens. As with the
subst rule, the target
must currently be phone or all the replacers of sizes corresponding
to their respective replacees.
Let us take a typical example:
prep preps.dic
where the referenced file contains a list of prepositions for the language, e.g. for Czech:
bez
do
k
ke
ku
na
nad
o
od
po
pod
pro
pRed
pRes pRez
s
u
v
ve
z
za
ze
You can see that most of the prepositions have the replacers
identical to the replacees, so that the preposition doesn't
change except for being merged to the left if found.
There is however one irregular monosyllabic preposition
in Czech which does change its behavior with regard to
the voicing assimilation in Czech, and this can be done
too as shown. Notice also that the unit
(here: the word) must match the dictionary item
exactly, as opposed to mere substring matching required
by the subst rule.
As a special case, if the parameter begins with an exclamation mark, then the rest of the parameter is parsed as usual and any substitutions are performed exactly as usual, but the scope units which get finally merged to their respective right hand neighbors are exactly those which are not found in the dictionary.
A typical example can be the following rule whose purpose is to abolish all syllable boundaries (within each word). The rule defines an empty dictionary and then merges each word which is not found in the dictionary and which has something to be merged to.
prep !"" syll
postpPostposition. See rule type prep for the description and examples, but the resultant unit is merged to its left-hand neighbor instead of the right-hand neighbor.
analyzeThis rule type analyzes a unit of level immediately below the scope level into a sequence of units based on a dictionary of known contents of the new units at the target level and priorities assigned to them. We will explain the operation of this rule in terms of the morphematic analysis, i.e. the most common use with the scope level being the word, the result of the analysis will be the morpheme level (just below the word level) and the target will be phones.
Each item of the dictionary corresponds to a single morpheme (some linguists would prefer to say "morph" here). The replacee is the form the result ofcept for any post-replacee and/or trailing whitespace, becomes the replacer. However, some rule types may not allow multiple word replacers.
The dictionaries follow the same conventions for character encoding, escaping special characters, inclusion directives and comments as the rule files and other text files.
Instead of a file name reference, it is possible to quote the contents of the dictionary directly; this is done by encapsulating the contents in double quotes. Dictionary items are in this case whitespace-separated, every replacer and replacee are separated by a comma.
The dictionary may either be parsed and loaded into memory at Epos startup
or at the moment of the first use. The former option's advantage is
early error reporting, while the latter can sometimes completely avoid
loading a huge unused dictionary. Use the option paranoid to choose
your preference.
subst Substring substitution. The replacers replace every occurrence of their respective replacees; longer matches are matched first; the process is iterated until no replacee occurs in the string. It there is a tie between several matches of equal length, the rightmost match is chosen.
It is required
either to have a phone target, or to keep all the replacers
and replacees the same length, because otherwise it is not obvious how to handle the
children of the units affected. Note also that to be considered a match
with the phone target, all characters other than phones also
have to match (must be found or not found on the same positions in both
the replacee and the occurrence in question) except for the terminating
scope-level separator (if any), which is invisible to this rule type.
Any replacer may begin with a ^ or end with a $. That forces the substring being replaced to be at the beginning or the end of the scope unit, respectively. This ^ or $ also counts as a character when determining the longest match.
The replacer should not contain units of the scope level or higher.
Unless the paranoid option is set, this is tolerated, but the
replacer is truncated at the first of such characters.
With the phone target, this rule type will drop the
internal structure of the replaced text as soon as a match is found.
In other words: an affected scope unit with a replacer is re-parsed as
any other plain text. With any other target the original structure
is always kept.
Infinitely looping substitutions are currently reported as an error condition.
As this rule type should not be used for trivial tasks with short and often matching dictionaries, the example we shall now give is somewhat involved:
< word syll
regress \ >m(!_!) word word
regress \ >d(!_!) word word
regress \ >t(!_!) word word
regress \ >q(!_!) word word
regress \ >p(!_!) word word
>
subst "^mmmmm,mmmxm ^mmmmmm,mmmxmm ^mmmmmmm,mmmmxmm \
pmm,pxm qmmm,qxmm pmmm,pxmm tmmmm,tmmxm qmmmm,qxmxm \
dmmmmm,dmmxmm tmmmmm,tmmxmm qmmmmm,qxmxmm pmmmmm,pxmmxm \
dmmmmmm,dmmxmmm tmmmmmm,tmmxmmm qmmmmmm,qxmmxmm \
pmmmmmm,pxmmxmm dmmmmmmm,dmmxmmxm tmmmmmmm,tmmxmmxm \
qmmmmmmm,qxmmmxmm pmmmmmmm,pxmmmxmm \
mmmmmmmm,mmmmxmmm" colon word
postp "m" word word
The purpose of this example sequence of rules is to form stress units out of graphical words, based on the following assumptions for the given language: polysyllables are retained as stress units, but following monosyllables may be merged to them; monosyllables which are colon-final should be retained; other monosyllables may merge to each other and/or to the preceding polysyllable; the merges should not produce too long stress units.
The first part of the example is used to mark all non-colon-final
(more exactly: space delimited) words with the letters m,d,t,q,p
based on the number of syllables; note that the p is used
not only for pentasyllables, but also for all words of more than five
syllables. Then the substition rule is used to relabel some
monosyllables (destined as heads of stress units consisting solely
of monosyllables) with x. Finally, all monosyllables that
haven't been relabeled to x are merged to the preceding
stress word if there is any using the postp rule.
The substitution rule in the example has 21 dictionary items,
the first three being applicable only at the colon-initial position.
Mostly it directly lists the resulting labeling for the whole
colon, but with extremely long sequences of monosyllables it
relies on the facts that the longest matching replacee (and the
rightmost one if there are multiple) is chosen and that the
substitution process is iterated. For example,
pmmmmmmmmm would be first relabeled to pmmmmmxmmm
using the last item as listed in the dictionary and then once more
using a different item to pxmmxmxmmm.
prep Preposition. If the scope unit is identical to some replacee,
it gets replaced with its respective replacer and merged to its right-hand
neighbor. If there is no such neighbor, nothing happens. As with the
subst rule, the target
must currently be phone or all the replacers of sizes corresponding
to their respective replacees.
Let us take a typical example:
prep preps.dic
where the referenced file contains a list of prepositions for the language, e.g. for Czech:
bez
do
k
ke
ku
na
nad
o
od
po
pod
pro
pRed
pRes pRez
s
u
v
ve
z
za
ze
You can see that most of the prepositions have the replacers
identical to the replacees, so that the preposition doesn't
change except for being merged to the left if found.
There is however one irregular monosyllabic preposition
in Czech which does change its behavior with regard to
the voicing assimilation in Czech, and this can be done
too as shown. Notice also that the unit
(here: the word) must match the dictionary item
exactly, as opposed to mere substring matching required
by the subst rule.
As a special case, if the parameter begins with an exclamation mark, then the rest of the parameter is parsed as usual and any substitutions are performed exactly as usual, but the scope units which get finally merged to their respective right hand neighbors are exactly those which are not found in the dictionary.
A typical example can be the following rule whose purpose is to abolish all syllable boundaries (within each word). The rule defines an empty dictionary and then merges each word which is not found in the dictionary and which has something to be merged to.
prep !"" syll
postpPostposition. See rule type prep for the description and examples, but the resultant unit is merged to its left-hand neighbor instead of the right-hand neighbor.
analyzeThis rule type analyzes a unit of level immediately below the scope level into a sequence of units based on a dictionary of known contents of the new units at the target level and priorities assigned to them. We will explain the operation of this rule in terms of the morphematic analysis, i.e. the most common use with the scope level being the word, the result of the analysis will be the morpheme level (just below the word level) and the target will be phones.
Each item of the dictionary corresponds to a single morpheme (some linguists would prefer to say "morph" here). The replacee is the form the result ofcept for any post-replacee and/or trailing whitespace, becomes the replacer. However, some rule types may not allow multiple word replacers.
The dictionaries follow the same conventions for character encoding, escaping special characters, inclusion directives and comments as the rule files and other text files.
Instead of a file name reference, it is possible to quote the contents of the dictionary directly; this is done by encapsulating the contents in double quotes. Dictionary items are in this case whitespace-separated, every replacer and replacee are separated by a comma.
The dictionary may either be parsed and loaded into memory at Epos startup
or at the moment of the first use. The former option's advantage is
early error reporting, while the latter can sometimes completely avoid
loading a huge unused dictionary. Use the option paranoid to choose
your preference.
subst Substring substitution. The replacers replace every occurrence of their respective replacees; longer matches are matched first; the process is iterated until no replacee occurs in the string. It there is a tie between several matches of equal length, the rightmost match is chosen.
It is required
either to have a phone target, or to keep all the replacers
and replacees the same length, because otherwise it is not obvious how to handle the
children of the units affected. Note also that to be considered a match
with the phone target, all characters other than phones also
have to match (must be found or not found on the same positions in both
the replacee and the occurrence in question) except for the terminating
scope-level separator (if any), which is invisible to this rule type.
Any replacer may begin with a ^ or end with a $. That forces the substring being replaced to be at the beginning or the end of the scope unit, respectively. This ^ or $ also counts as a character when determining the longest match.
The replacer should not contain units of the scope level or higher.
Unless the paranoid option is set, this is tolerated, but the
replacer is truncated at the first of such characters.
With the phone target, this rule type will drop the
internal structure of the replaced text as soon as a match is found.
In other words: an affected scope unit with a replacer is re-parsed as
any other plain text. With any other target the original structure
is always kept.
Infinitely looping substitutions are currently reported as an error condition.
As this rule type should not be used for trivial tasks with short and often matching dictionaries, the example we shall now give is somewhat involved:
< word syll
regress \ >m(!_!) word word
regress \ >d(!_!) word word
regress \ >t(!_!) word word
regress \ >q(!_!) word word
regress \ >p(!_!) word word
>
subst "^mmmmm,mmmxm ^mmmmmm,mmmxmm ^mmmmmmm,mmmmxmm \
pmm,pxm qmmm,qxmm pmmm,pxmm tmmmm,tmmxm qmmmm,qxmxm \
dmmmmm,dmmxmm tmmmmm,tmmxmm qmmmmm,qxmxmm pmmmmm,pxmmxm \
dmmmmmm,dmmxmmm tmmmmmm,tmmxmmm qmmmmmm,qxmmxmm \
pmmmmmm,pxmmxmm dmmmmmmm,dmmxmmxm tmmmmmmm,tmmxmmxm \
qmmmmmmm,qxmmmxmm pmmmmmmm,pxmmmxmm \
mmmmmmmm,mmmmxmmm" colon word
postp "m" word word
The purpose of this example sequence of rules is to form stress units out of graphical words, based on the following assumptions for the given language: polysyllables are retained as stress units, but following monosyllables may be merged to them; monosyllables which are colon-final should be retained; other monosyllables may merge to each other and/or to the preceding polysyllable; the merges should not produce too long stress units.
The first part of the example is used to mark all non-colon-final
(more exactly: space delimited) words with the letters m,d,t,q,p
based on the number of syllables; note that the p is used
not only for pentasyllables, but also for all words of more than five
syllables. Then the substition rule is used to relabel some
monosyllables (destined as heads of stress units consisting solely
of monosyllables) with x. Finally, all monosyllables that
haven't been relabeled to x are merged to the preceding
stress word if there is any using the postp rule.
The substitution rule in the example has 21 dictionary items,
the first three being applicable only at the colon-initial position.
Mostly it directly lists the resulting labeling for the whole
colon, but with extremely long sequences of monosyllables it
relies on the facts that the longest matching replacee (and the
rightmost one if there are multiple) is chosen and that the
substitution process is iterated. For example,
pmmmmmmmmm would be first relabeled to pmmmmmxmmm
using the last item as listed in the dictionary and then once more
using a different item to pxmmxmxmmm.
prep Preposition. If the scope unit is identical to some replacee,
it gets replaced with its respective replacer and merged to its right-hand
neighbor. If there is no such neighbor, nothing happens. As with the
subst rule, the target
must currently be phone or all the replacers of sizes corresponding
to their respective replacees.
Let us take a typical example:
prep preps.dic
where the referenced file contains a list of prepositions for the language, e.g. for Czech:
bez
do
k
ke
ku
na
nad
o
od
po
pod
pro
pRed
pRes pRez
s
u
v
ve
z
za
ze
You can see that most of the prepositions have the replacers
identical to the replacees, so that the preposition doesn't
change except for being merged to the left if found.
There is however one irregular monosyllabic preposition
in Czech which does change its behavior with regard to
the voicing assimilation in Czech, and this can be done
too as shown. Notice also that the unit
(here: the word) must match the dictionary item
exactly, as opposed to mere substring matching required
by the subst rule.
As a special case, if the parameter begins with an exclamation mark, then the rest of the parameter is parsed as usual and any substitutions are performed exactly as usual, but the scope units which get finally merged to their respective right hand neighbors are exactly those which are not found in the dictionary.
A typical example can be the following rule whose purpose is to abolish all syllable boundaries (within each word). The rule defines an empty dictionary and then merges each word which is not found in the dictionary and which has something to be merged to.
prep !"" syll
postpPostposition. See rule type prep for the description and examples, but the resultant unit is merged to its left-hand neighbor instead of the right-hand neighbor.
analyzeThis rule type analyzes a unit of level immediately below the scope level into a sequence of units based on a dictionary of known contents of the new units at the target level and priorities assigned to them. We will explain the operation of this rule in terms of the morphematic analysis, i.e. the most common use with the scope level being the word, the result of the analysis will