MMORPH(5)
π¦ MMORPH(5) π¦
File Formats Manual β the MULTEXT morphology tool, and yes we're doing the whole syntax together bestie
π NAME π
mmorphβ MULTEXT morphology tool formalism syntax
β¨ DESCRIPTION β¨
okay so listen. A mmorph morphology description file is divided into declaration sections. Every section starts with a section header (think @ Alphabets, @ Attributes, etc.) and then a whole lil parade of declarations follows it. And each declaration? Starts with a name, then a colon (:), then the definition that belongs to that name. That's the whole shape of it. Here's the quick tour of every section, no skipping, promise π«Ά:
π€ @ Alphabets π€
This is where the lexical and surface alphabet get declared. You have to list every single symbol that forms each alphabet β all of them, no gatekeeping. A symbol can show up in both the lexical and the surface alphabet definition, and in that case it's a bi-level symbol. If it doesn't, it's lexical only or surface only.
Symbols are usually just letters (eg. a, b, c), but they can also be longer names like beta or schwa. And if a symbol name is literally one special character β like : or ( β you can specify it by wrapping it in double quotes.
Example:
Lexical : a b c d e f g h i j k l m n o p q r s t u v w x y z "-"
"." "," "?" "!" "\"" "'" ":" ";" "(" ")" strong_e
Surface : a b c d e f g h i j k l m n o p q r s t u v w x y z "-"
"." "," "?" "!" "\"" "'" ":" ";" "(" ")" " "
So in this example, strong_e is lexical only, and the symbol " " (a space) is surface only. Every other symbol in there is bi-level. π
And fr fr: all the strings that show up anywhere else in the grammar will be made exclusively out of symbols declared in this section. Nothing else gets in. Periodt.
π @ Attributes π
Here you declare the name of attributes (some people call them features, same thing) and their associated value set. And heads up: at most 32 different values may be declared for an attribute. That's the cap, bestie.
Examples:
Gender : feminine masculine neuter
Number : singular plural
Person : 1st 2nd 3rd
Transitive : yes no
Inflection : base intermediate final
Now for the annoying part: in the current version of the implementation, value sets of different attributes are incompatible, even if they're defined identically. Like, identical twins but they still can't sit together. To get around this restriction, in a future version this section will be split into two: declaration of value sets, and declaration of attributes.
π§ @ Types π§
This section declares the different types of feature structures. For each type, you list the attributes allowed for it. And here's a cute detail β attributes that are only used within the scope of the tool and have no meaning outside can be listed after a bar (|). The values of these local attributes are not stored in the database and not written on the final output of the program. Iconic, honestly.
Examples:
Noun : Gender Number
Verb : Tense Person Gender Number Transitive | Inflection
π« Typed feature structures π«
Typed feature structures get used in the grammar and spelling rules. A typed feature structure is the specification of a type plus the value of some associated attributes. The list of attribute specifications goes inside square brackets ([ and ]).
Example:
Noun[ Gender=feminine Number=singular ]
You can also specify a whole set of values for an attribute by listing the possible values separated with a bar (|), or the complement of a set β that's with respect to all possible values of that attribute β by using != instead of =.
Example: assuming the declaration of Gender as above, the following two typed feature structures are equivalent:
Noun[ Gender=masculine|neuter ]
Noun[ Gender!=feminine ]
π @ Grammar π
This section holds the rules that specify the structure of words. Its general shape is a context free grammar over typed feature structures. There are three basic types of rules: binary, goal and affixes. Let's go one by one.
Binary rules specify the result of the concatenation of two elements. Written like this:
Rule_name : Lhs <- Rhs1 Rhs2
where Lhs is called the left hand side, and Rhs1 and Rhs2 are the first and second part of the right hand side. Lhs, Rhs1 and Rhs2 are all specified as typed feature structures.
Example:
Rule_1 : Noun[ Gender=feminine Number=singular ]
<- Noun[ Gender=feminine Number=singular ]
NounSuffix[ Gender=feminine ]
Variables can be used to indicate that some attributes have the same value. A variable is a name starting with a dollar ($).
Example:
Rule_2 : Noun[ Gender=$A Number=$number ]
<- Noun[ Gender=$A Number=$number ]
NounSuffix[ Gender=$A ]
If needed, you can give both a variable and a value specification for an attribute β but only once per attribute, don't get greedy.
Example:
Rule_3 : Noun[ Gender=$A Number=$number ]
<- Noun[ Gender=$A Number=$number ]
NounSuffix[ Gender=$A=masculine|neuter ]
Affix rules define the basic elements of the concatenations specified by binary rules (together with lexical entries β see the section @ Lexicon below, we'll get there). An affix rule consists of a lexical string associated to a typed feature structure.
Examples:
Plural_s : "s" NounSuffix[ Number=plural ]
Feminine_e : "e" NounSuffix[ Gender=feminine ]
ing : "ing" VerbSuffix[ Tense=present_participle ]
Goal rules specify the valid results constructed by the grammar. They're just a typed feature structure and nothing else. So simple, so chic.
Examples:
Goal_1 : Noun[]
Goal_2 : Verb[ inflection=final ]
And on top of those three basic rule types, there are also prefix or suffix composite rules and unary rules. A unary rule consists of a left hand side and a right hand side.
Example:
Rule_4 : Noun[ gender=$G number=plural ]
<- Noun[ gender=$G number=singular invariant=yes]
Prefix and suffix composite rules have the same shape as binary rules, except that one part of the right hand side is an affix (i.e. it has an associated string).
Examples:
Append_e : Noun[ Gender=feminine Number=$number ]
<- Noun[ Gender=feminine Number=$number ]
"e" NounSuffix[ Gender=feminine ]
anti : Noun[ Gender=$gender Number=$number ]
<- "anti" NounPrefix[]
Noun[ Gender=$gender Number=$number ]
π @ Classes π
This section is optional. It contains the definition of symbol classes. Each class is defined as a set of symbols, or other classes. If the class contains only bi-level elements, it's a bi-level class β otherwise it's a lexical or surface class.
Examples:
Dental : d t
Vowel : a e i o u
Vowel_y : Vowel y
Consonant: b c d f g h j k l m n p q r s t v w x z
π¦ @ Pairs π¦
This section is also optional. It contains the definition of pair disjunctions. Each disjunction is defined as a set of pairs.
Explicit pairs specify a sequence of surface symbols and a sequence of zero or one lexical symbol, one of them possibly empty. A sequence is enclosed between angle brackets < and >. The empty sequence is indicated with <>. And lowkey important: in the current implementation, only the surface part of a pair can be a sequence of more than one element. The special symbol ? stands for the class of all possible symbols, including the morpheme and word boundary.
Examples:
s_x_z_1 : s/s x/x z/z
VowelPair1: a/a e/e i/i o/o u/u
VowelPair2: Vowel/Vowel
ie.y: <i e>/y
Delete_e: <>/e
Insert_d: d/<>
Surface_Vowel: Vowel/?
Lexical_s: ?/s
DoubleConsonant: <b b>/b <d d>/d <f f>/f <g g>/g <k k>/k <m m>/m
<p p>/p <s s>/s <t t>/t <v v>/v <z z>/z
Note that VowelPair1 and VowelPair2 don't specify the same thing: VowelPair2 would match a/o but VowelPair1 would not. π
Implicit pairs are specified by the name of a bi-level symbol or a bi-level class.
Examples: the following s_x_z_2 and VowelPair3 are equivalent to the above s_x_z_1 and VowelPair2 (assuming that s, x, z and Vowel are bi-level symbols and classes).
s_x_z_2 : s x z
VowelPair3 : Vowel
Now for a rule that will bite you: in a pair disjunction all lexical parts should be disjoint. That means you cannot specify, for the same pair disjunction, a/a and o/a, or a/a and Vowel/Vowel. Not allowed, bestie. π«
Also, in a future version this section will be split in two: simple pair disjunctions, and pair sequences.
πΈ @ Spelling πΈ
This section is where the two level spelling rules get declared. A spelling rule consists of a kind indicator followed by a left context, a focus and a right context.
The kind indicator is:
=>if the rule is optional<=>if it is obligatory<=if it is a surface coercion rule
The contexts may be empty. The focus is surrounded by two -. The contexts and the focus consist of a sequence of pairs or pair disjunctions declared in the @ Pairs section. A morpheme boundary is indicated by a + or a *, and a word boundary is indicated by a ~.
Examples:
Sibilant_s: <=> s_x_z_1 * - e/<> - s
Gemination: <=>
Consonant Vowel - DoubleConsonant - * Vowel
i_y_optionnel: => a - i/y - * ?/e
Constraints may be specified in the form of a list of typed feature structures. They're affix-driven: the rule is licensed if at least one of them subsumes the closest corresponding affix. The morpheme boundary indicated by a star (*) will be used to determine which affix it is. If there's no such indication, then the affix adjacent to the morpheme where the first character of the focus occurs is the one that gets used. And in case there is no affix, the typed feature structure of the lexical stem is used.
Example:
Sibilant_s: <=>
s_x_z_1 * - e/<> - s NounSuffix[ Number=plural ]
π @ Lexicon π
This section is optional and it can also be repeated β go off. It lists all the lexical entries of the morphological description.
And here's the twist: unlike the other sections, definitions do not have a name. π A definition consists of a typed feature structure followed by a list of lexical stems that share that feature structure. A lexical stem consists of the string used in the concatenation specified by the grammar rules, followed by = and a reference string. The reference string can be anything, and it's usually used to indicate the canonical form of the word or an identifier of an external database entry.
Examples:
Noun[ Number=singular ] "table" = "table" "chair" = "chair"
Verb[ Transitive=yes|no Inflection=base ] "bow" = "bow1"
Noun[ Number=singular ] "bow" = "bow2"
And if the stem string and the reference string are identical, you only need to specify one of them. Efficient. We love that.
Example:
Noun[ Number=singular ] "table" "chair"
π FORMAL SYNTAX π
okay bestie, here's the formal syntax, and it's giving Backus Naur Form (BNF) energy π . The conventions are:
<id>β is a non-terminal symbol (within angle brackets).IDβ is a token (terminal symbol, all uppercase).<id>?β means zero or one occurrence of<id>(i.e.<id>is optional).<id>*β is zero or more occurrences of<id>.<id>+β is one or more occurrences of<id>.::=β separates a non-terminal symbol and its expansion.|β indicates an alternative expansion.;β starts a comment (not part of the definition).
The start symbol corresponding to a complete description is named <Start>. Symbols that parse but do nothing are marked with ; not operational.
<Start> ::= <AlphabetDecl> <AttDecl> <TypeDecl> <GramDecl>
<ClassDecl>? <PairDecl>? <SpellDecl>? <LexDecl>*
<AlphabetDecl> ::= ALPHABETS <LexicalDef> <SurfaceDef>
<LexicalDef> ::= <LexicalName> COLON <LexicalSymbol>+
<SurfaceDef> ::= <SurfaceName> COLON <SurfaceSymbol>+
<LexicalSymbol> ::= <LexicalSymbolName> ; lexical only
| <BiLevelSymbolName> ; both lexical and surface
<SurfaceSymbol> ::= <SurfaceSymbolName> ; surface only
| <BiLevelSymbolName> ; both lexical and surface
<AttDecl> ::= ATTRIBUTES <AttDef>+
<AttDef> ::= <AttName> COLON <ValName>+
<TypeDecl> ::= TYPES <TypeDef>+
<TypeDef> ::= <TypeName> COLON <AttName>+ <NoProjAtt>?
<NoProjAtt> ::= BAR <AttName>+
<LexDecl> ::= LEXICON <LexDef>+
<LexDef> ::= <Tfs> <Lexical>+
<Lexical> ::= LEXICALSTRING <BaseForm>?
<BaseForm> ::= EQUAL LEXICALSTRING
<Tfs> ::= <TypeName> <AttSpec>?
<VarTfs> ::= <TypeName> <VarAttSpec>?
<AttSpec> ::= LBRA <AttVal>* RBRA
<VarAttSpec> ::= LBRA <VarAttVal>* RBRA
<AttVal> ::= <AttName> <ValSpec>
<VarAttVal> ::= <AttName> <VarValSpec>
<ValSpec> ::= EQUAL <ValSet>
| NOTEQUAL <ValSet>
<VarValSpec> ::= <ValSpec>
| EQUAL DOLLAR <VarName>
| EQUAL DOLLAR <VarName> <ValSpec>
<ValSet> ::= <ValName> <ValSetRest>*
<ValSetRest> ::= BAR <ValName>
<GramDecl> ::= GRAMMAR <Rule>+
<RuleDef> ::= <RuleName> COLON <RuleBody>
<RuleBody> ::= <VarTfs> LARROW <Rhs>
| <Tfs> ; goal rule
| LEXICALSTRING <Tfs> ; lexical affix
<Rhs> ::= <VarTfs> ; unary rule
| <VarTfs> <VarTfs> ; binary rule
| LEXICALSTRING <Tfs> <VarTfs> ; prefix rule
| <VarTfs> <Tfs> LEXICALSTRING ; suffix rule
<ClassDecl> ::= CLASSES<ClassDef>+
<ClassDef> ::= <LexicalClassName> COLON <LexicalClass>+
| <SurfaceClassName> COLON <SurfaceClass>+
| <BiLevelClassName> COLON <BiLevelClass>+
<LexicalClass> ::= <LexicalSymbol>
| <LexicalClassName>
| <BiLevelClassName>
<SurfaceClass> ::= <SurfaceSymbol>
| <SurfaceClassName>
| <BiLevelClassName>
<BiLevelClass> ::= <BiLevelSymbolName>
| <BiLevelClassName>
<PairDecl> ::= PAIRS <PairDef>+
<PairDef> ::= <PairName> COLON <PairDef>+
<PairDef> ::= <PairName> COLON <Pair>+
<Pair> ::= <SurfaceSequence> SLASH <LexicalSequence>
| <PairName>
| <BiLevelClassName>
| <BiLevelSymbolName>
SurfaceSequence ::= LANGLE <SurfaceSymbol>* RANGLE
| SURFACESTRING
| <SurfaceClass>
| ANY
LexicalSequence ::= LANGLE <LexicalSymbol>* RANGLE
| LEXICALSTRING
| <LexicalClass>
| ANY
<SpellDecl> ::= SPELLING <SpellDef>+
<SpellDef> ::= <SpellName> COLON <Arrow> <LeftContext> <Focus>
<RightContext> <Constraint>*
<LeftContext> ::= <Pattern>*
<RightContext> ::= <Pattern>*
<Focus> ::= CONTEXTBOUNDARY <Pattern>+ CONTEXTBOUNDARY
<Pattern> ::= <Pair>
| MORPHEMEBOUNDARY
| WORDBOUNDARY
| CONCATBOUNDARY
<Constraint> ::= <Tfs>
<Arrow> ::= RARROW
| BIARROW
| COERCEARROW
<AttName> ::= NAME
<BiLevelClassName> ::= NAME
<BiLevelSymbolName> ::= NAME | SYMBOLSTRING
<LexicalClassName> ::= NAME
<LexicalName> ::= NAME
<LexicalSymbolName> ::= NAME | SYMBOLSTRING
<PairName> ::= NAME
<RuleName> ::= NAME
<SpellName> ::= NAME
<SurfaceClassName> ::= NAME
<SurfaceName> ::= NAME
<SurfaceSymbolName> ::= NAME | SYMBOLSTRING
<TypeName> ::= NAME
<ValName> ::= NAME
<VarName> ::= NAME
β¨ Simple tokens β¨
Simple tokens of the BNF above are defined as follow: The token name on the left correspond to the literal character or characters on the right:
ANY ?
BAR |
BIARROW <=>
COERCEARROW <=
COLON :
CONCATBOUNDARY *
CONTEXTBOUNDARY -
DOLLAR $
EQUAL =
LANGLE <
LARROW <-
LBRA ]
MORPHEMEBOUNDARY +
NOTEQUAL !=
RARROW =>
RANGLE <
RBRA [
SLASH /
WORDBOUNDARY ~
ALPHABETS @Alphabets
ATTRIBUTES @Attributes
CLASSES @Classes
GRAMMAR @Grammar
LEXICON @Lexicon
PAIRS @Pairs
SPELLING @Spelling
TYPES @Types
In the section header tokens above, spaces may separate the @ from the reserved word. cute, right? π«Ά
π¦ Complex tokens π¦
NAMEβ is any sequence of letter, digit, underline (_), period (.). Examples:
category
33
Rule_9
__2__
Proper.Noun
LEXICALSTRINGβ is a string of lexical symbols.SURFACESTRINGβ is a string of surface symbols.SYMBOLSTRINGβ is a string of just just one character (used only in alphabet declaration). (yes bestie, the double "just" is canon, I don't make the rules π)
A string consist of zero or more characters within double quotes ("). Characters preceded by a backslash (\) are escaped (the usual C escaping convention apply). Symbols that have a name longer than one character are represented using a SGML entity like notation: &symbolname;. The maximum number of symbols in a string is 127. Examples:
"table"
","
""
"double quote is \" and backslash is \\"
"&strong_e;"
"escape like in C : \t is ASCII tab"
"escape with octal code: \011 is ASCII tab"
Tokens can be separated by one or many blanks or comments. A blank separator is space, tab or newline. A comment starts with a semicolon and finishes at the next newline (except when the semicolon occurs in a string.
Inclusion of files can be specified with the usual #include directive:
Example:
#include "verb.entries"
will splice in the content of the file verb.entries at the point where this directive occurs.
The # should be the first character on the line. Tabs or spaces may separate # and include. The file name must be quoted. Only tabs or spaces may occur on the rest of the line. Inclusion can be nested up to 10 levels. no cap, ten whole levels π«
π SEE ALSO π
mmorph(1).- G. Russell and D. Petitpierre, MMORPH - The Multext Morphology Program, Version 2.3, October 1995, MULTEXT deliverable report for task 2.3.1.
π AUTHOR π
Dominique Petitpierre, ISSCO, <petitp@divsun.unige.ch>
π¬ COMMENTS π¬
The parser for the morphology description formalims above was written using yacc (1) and flex (1). Flex was written by Vern Paxson, <vern@ee.lbl.gov>, and is distributed in the framework of the GNU project under the condition of the GNU General Public License
and that's the whole vibe, bestie β this page is from Version 2.3, October 1995, and it's literally titled MMORPH(5) πβ¨ you ate, fr fr π
π¦ where this page comes from
- ubuntu jammy: mmorph 2.3.4.2-17 Β· GPL-2.0-or-later
- Copyright (c) 1994,1995 ISSCO/SUISSETRA, Geneva, Switzerland
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms