resource examples

This commit is contained in:
aarne
2005-12-19 16:31:40 +00:00
parent 7878cd5e0a
commit bfbe2e3d47
19 changed files with 1040 additions and 207 deletions

View File

@@ -5,9 +5,9 @@ abstract Foods = {
fun
Is : Item -> Quality -> S ;
This, That, All, Most : Kind -> Item ;
This, That, These, Those : Kind -> Item ;
QKind : Quality -> Kind -> Kind ;
Wine, Cheese, Fish : Kind ;
Wine, Cheese, Fish, Pizza : Kind ;
Very : Quality -> Quality ;
Fresh, Warm, Italian, Expensive, Delicious, Boring : Quality ;

View File

@@ -1,4 +1,4 @@
--# -path=.:prelude
--# -path=.:resource:prelude
concrete FoodsEng of Foods = open Prelude, MorphoEng in {
@@ -9,14 +9,15 @@ concrete FoodsEng of Foods = open Prelude, MorphoEng in {
lin
Is item quality = ss (item.s ++ (mkVerb "are" "is").s ! item.n ++ quality.s) ;
This = det Sg "this" ;
That = det Sg "that" ;
All = det Pl "all" ;
Most = det Pl "most" ;
This = det Sg "this" ;
That = det Sg "that" ;
These = det Pl "these" ;
Those = det Pl "those" ;
QKind quality kind = {s = \\n => quality.s ++ kind.s ! n} ;
Wine = regNoun "wine" ;
Cheese = regNoun "cheese" ;
Fish = mkNoun "fish" "fish" ;
Pizza = regNoun "pizza" ;
Very = prefixSS "very" ;
Fresh = ss "fresh" ;
Warm = ss "warm" ;

View File

@@ -0,0 +1,12 @@
abstract Comments = {
cat
S ; Item ; Kind ; Quality ;
fun
Is : Item -> Quality -> S ;
This, That, These, Those : Kind -> Item ;
QKind : Quality -> Kind -> Kind ;
Very : Quality -> Quality ;
}

View File

@@ -0,0 +1,2 @@
concrete CommentsEng of Comments = CommentsI with
(Syntax = SyntaxEng) ;

View File

@@ -0,0 +1,21 @@
--# -path=.:prelude
incomplete concrete CommentsI of Comments = open Syntax in {
lincat
S = Syntax.S ;
Quality = AP ;
Kind = CN ;
Item = NP ;
lin
Is item quality = PosVP item (PredAP quality) ;
This = DetCN this_Det ;
That = DetCN that_Det ;
These = DetCN these_Det ;
Those = DetCN those_Det ;
QKind = ModCN ;
Very = AdAP very_AdA ;
}

View File

@@ -0,0 +1,2 @@
concrete CommentsIta of Comments = CommentsI with
(Syntax = SyntaxIta) ;

View File

@@ -0,0 +1,7 @@
abstract FoodComments = Comments ** {
fun
Wine, Cheese, Fish, Pizza : Kind ;
Fresh, Warm, Italian, Expensive, Delicious, Boring : Quality ;
}

View File

@@ -0,0 +1,18 @@
--# -path=.:../resource:prelude
concrete FoodCommentsEng of FoodComments = CommentsEng ** open LexEng in {
lin
Wine = regN "wine" ;
Cheese = regN "cheese" ;
Fish = mkN "fish" "fish" ;
Pizza = regN "pizza" ;
Fresh = mkA "fresh" ;
Warm = mkA "warm" ;
Italian = mkA "Italian" ;
Expensive = mkA "expensive" ;
Delicious = mkA "delicious" ;
Boring = mkA "boring" ;
}

View File

@@ -0,0 +1,17 @@
--# -path=.:../resource:prelude
concrete FoodCommentsIta of FoodComments = CommentsIta ** open LexIta in {
lin
Wine = regN "vino" ;
Cheese = mkN masculine "formaggio" "formaggi" ;
Fish = regN "pesce" ;
Pizza = regN "pizza" ;
Fresh = mkA "fresco" "fresca" "freschi" "fresche" ;
Warm = regA "caldo" ;
Italian = regA "italiano" ;
Expensive = regA "caro" ;
Delicious = regA "delizioso" ;
Boring = regA "noioso" ;
}

File diff suppressed because it is too large Load Diff

View File

@@ -8,12 +8,23 @@ Last update: %%date(%c)
%!target:html
% workaround for some missing things in the format
% %!postproc(html): C- <center>
% %!postproc(html): -C </center>
% %!postproc(html): t- <tt>
% %!postproc(html): -t </tt>
[../gf-logo.gif]
%--!
==GF = Grammatical Framework==
==Introduction==
===GF = Grammatical Framework===
The term GF is used for different things:
@@ -32,6 +43,143 @@ It will guide you
%--!
===What are GF grammars used for===
A grammar is a definition of a language.
From this definition, different language processing components
can be derived:
- parsing: to analyse the language
- linearization: to generate the language
- translation: to analyse one language and generate another
A GF grammar can be seen as a declarative program from which these
processing tasks can be automatically derived. In addition, many
other tasks are readily available for GF grammars:
- morphological analysis: find out the possible inflection forms of words
- morphological synthesis: generate all inflection forms of words
- random generation: generate random expressions
- corpus generation: generate all expressions
- teaching quizzes: train morphology and translation
- multilingual authoring: create a document in many languages simultaneously
- speech input: optimize a speech recognition system for your grammar
A typical GF application is based on a **multilingual grammar** involving
translation on a special domain. Existing applications of this idea include
- [Alfa: http://www.cs.chalmers.se/%7Ehallgren/Alfa/Tutorial/GFplugin.html]:
a natural-language interface to a proof editor
(languages: English, French, Swedish)
- [KeY http://www.key-project.org/]:
a multilingual authoring system for creating software specifications
(languages: OCL, English, German)
- [TALK http://www.talk-project.org]:
multilingual and multimodal dialogue systems
- [WebALT http://webalt.math.helsinki.fi/content/index_eng.html]:
a multilingual translator of mathematical exercises
(languages: Catalan, English, Finnish, French, Spanish, Swedish)
- [Numeral translator http://www.cs.chalmers.se/~bringert/gf/translate/]:
number words from 1 to 999,999
(88 languages)
The specialization of a grammar to a domain makes it possible to
obtain much better translations than in an unlimited machine translation
system. This is due to the well-defined semantics of such domains.
Grammars having this character are called **application grammars**.
They are different from most grammars written by linguists just
because they are multilingual and domain-specific.
However, there is another kind of grammars, which we call **resource grammars**.
These are large, comprehensive grammars that can be used on any domain.
The GF Resource Grammar Library has resource grammars for 10 languages.
These grammars can be used as **libraries** to define application grammars.
In this way, it is possible to write a high-quality grammar without
knowing about linguistics: in general, to write an application grammar
by using the resource library just requires practical knowledge of
the target language.
%--!
===Who is this tutorial for===
This tutorial is mainly for programmers who want to learn to write
application grammars. It will go through GF's programming concepts
without entering too deep into linguistics. Thus it should
be accessible to anyone who has some previous programming experience.
A separate document is being written on how to write resource grammars.
This includes the ways in which linguistic problems posed by different
languages are solved in GF.
%--!
===The coverage of the tutorial===
The tutorial gives a hands-on introduction to grammar writing.
We start by building a small grammar for the domain of food:
in this grammar, you can say things like
``` this Italian cheese is delicious
in English and Italian.
The first English grammar
[``food.cf`` food.cf]
is written in a context-free
notation (also known as BNF). The BNF format is often a good
starting point for GF grammar development, because it is
simple and widely used. However, the BNF format is not
good for multilingual grammars. While it is possible to
translate the words contained in a BNF grammar to another
language, proper translation usually involves more, e.g.
changing the word order in
``` Italian cheese ===> formaggio italiano
The full GF grammar format is designed to support such
changes, by separating between the **abstract syntax**
(the logical structure) and the **concrete syntax** (the
sequence of words) of expressions.
There is more than words and word order that makes languages
different. Words can have different forms, and which forms
they have vary from language to language. For instance,
Italian adjectives usually have four forms where English
has just one:
```
delicious (wine | wines | pizza | pizzas)
vino delizioso, vini deliziosi, pizza deliziosa, pizze deliziose
```
The **morphology** of a language describes the
forms of its words. While the complete description of morphology
belongs to resource grammars, the tutorial will explain the
main programming concepts involved. This will moreover
make it possible to grow the fragment covered by the food example.
The tutorial will in fact build a toy resource grammar in order
to illustrate the module structure of library-based application
grammar writing.
Thus it is by elaborating the initial ``food.cf`` example that
the tutorial makes a guided tour through all concepts of GF.
While the constructs of the GF language are the main focus,
also the commands of the GF system are introduced as they
are needed.
To learn how to write GF grammars is not the only goal of
this tutorial. To learn the commands of the GF system means
that simple applications of grammars, such as translation and
quiz systems, can be built simply by writing scripts for the
system. More complicated applications, such as natural-language
interfaces and dialogue systems, also require programming in
some general-purpose language. We will briefly explain how
GF grammars are used as components of Haskell, Java, and
Prolog grammars. The tutorial concludes with a couple of
case studies showing how such complete systems can be built.
%--!
===Getting the GF program===
@@ -74,7 +222,7 @@ follow them.
%--!
==The ``.cf`` grammar format==
==The .cf grammar format==
Now you are ready to try out your first grammar.
We start with one that is not written in GF language, but
@@ -1186,7 +1334,7 @@ A common idiom is to
gather the ``oper`` and ``param`` definitions
needed for inflecting words in
a language into a morphology module. Here is a simple
example, [``MorphoEng`` MorphoEng.gf].
example, [``MorphoEng`` resource/MorphoEng.gf].
```
--# -path=.:prelude
@@ -1302,7 +1450,7 @@ the predication structure:
The following section will present
``FoodsEng``, assuming the abstract syntax ``Foods``
that is similar to ``Food`` but also has the
plural determiners ``All`` and ``Most``.
plural determiners ``These`` and ``Those``.
The reader is invited to inspect the way in which agreement works in
the formation of sentences.
@@ -1310,8 +1458,14 @@ the formation of sentences.
%--!
===English concrete syntax with parameters===
The grammar uses both
[``Prelude`` ../../lib/prelude/Prelude.gf] and
[``MorphoEng`` resource/MorphoEng].
We will later see how to make the grammar even
more high-level by using a resource grammar library
and parametrized modules.
```
--# -path=.:prelude
--# -path=.:resource:prelude
concrete FoodsEng of Foods = open Prelude, MorphoEng in {
@@ -1322,10 +1476,10 @@ concrete FoodsEng of Foods = open Prelude, MorphoEng in {
lin
Is item quality = ss (item.s ++ (mkVerb "are" "is").s ! item.n ++ quality.s) ;
This = det Sg "this" ;
That = det Sg "that" ;
All = det Pl "all" ;
Most = det Pl "most" ;
This = det Sg "this" ;
That = det Sg "that" ;
These = det Pl "these" ;
Those = det Pl "those" ;
QKind quality kind = {s = \\n => quality.s ++ kind.s ! n} ;
Wine = regNoun "wine" ;
Cheese = regNoun "cheese" ;
@@ -1375,14 +1529,23 @@ it would be inaccurate to define adjective paradigms using the type
yields an accurate system of three adjectival forms.
```
param AdjForm = ASg Gender | APl ;
param Gender = Uter | Neuter ;
param Gender = Utr | Neutr ;
```
In pattern matching, a constructor can have patterns as arguments. For instance,
the adjectival paradigm in which the two singular forms are the same, can be defined
Here is an example of pattern matching, the paradigm of regular adjectives.
```
oper plattAdj : Str -> AdjForm => Str = \x -> table {
ASg _ => x ;
APl => x + "a" ;
oper regAdj : Str -> AdjForm => Str = \fin -> table {
ASg Utr => fin ;
ASg Neutr => fin + "t" ;
APl => fin + "a" ;
}
```
A constructor can have patterns as arguments. For instance,
the adjectival paradigm in which the two singular forms are the same,
can be defined
```
oper plattAdj : Str -> AdjForm => Str = \platt -> table {
ASg _ => platt ;
APl => platt + "a" ;
}
```
@@ -1437,8 +1600,8 @@ The first of the following judgements defines transitive verbs as
type with two strings and not just one. The second judgement
shows how the constituents are separated by the object in complementization.
```
lincat TV = {s : Number => Str ; s2 : Str} ;
lin ComplTV tv obj = {s = \\n => tv.s ! n ++ obj.s ++ tv.s2} ;
lincat TV = {s : Number => Str ; part : Str} ;
lin PredTV tv obj = {s = \\n => tv.s ! n ++ obj.s ++ tv.part} ;
```
There is no restriction in the number of discontinuous constituents
(or other fields) a ``lincat`` may contain. The only condition is that
@@ -1455,6 +1618,30 @@ field labelled ``s``.
==More constructs for concrete syntax==
%--!
===Local definitions===
Local definitions ("``let`` expressions") are used in functional
programming for two reasons: to structure the code into smaller
expressions, and to avoid repeated computation of one and
the same expression. Here is an example, from
[``MorphoIta resource/MorphoIta.gf]:
```
oper regNoun : Str -> Noun = \vino ->
let
vin = init vino ;
o = last vino
in
case o of {
"a" => mkNoun Fem vino (vin + "e") ;
"o" | "e" => mkNoun Masc vino (vin + "i") ;
_ => mkNoun Masc vino vino
} ;
```
%--!
===Free variation===
@@ -1464,7 +1651,7 @@ For instance, the verb negation in English can be expressed both by
are in **free variation**. The ``variants`` construct of GF can
be used to give a list of strings in free variation. For example,
```
NegVerb verb = {s = variants {["does not"] ; "doesn't} ++ verb.s} ;
NegVerb verb = {s = variants {["does not"] ; "doesn't} ++ verb.s ! Pl} ;
```
An empty variant list
```
@@ -1542,14 +1729,13 @@ This very example does not work in all situations: the prefix
```
===Predefined types and operations===
GF has the following predefined categories in abstract syntax:
```
cat Int ; -- integers, e.g. 0, 5, 743145151019
cat Float ; -- floats, e.g. 0.0, 3.1415926
cat String ; -- strings, e.g. "", "foo", "123"
cat Float ; -- floats, e.g. 0.0, 3.1415926
cat String ; -- strings, e.g. "", "foo", "123"
```
The objects of each of these categories are **literals**
as indicated in the comments above. No ``fun`` definition

View File

@@ -0,0 +1,34 @@
--# -path=.:prelude
resource LexEng = open SyntaxEng, MorphoEng, Prelude in {
oper
-- constructors for open lexicon
mkN : (man,men : Str) -> CN ;
regN : (car : Str) -> CN ;
mkA : (hot : Str) -> AP ;
mkV : (go,goes : Str) -> V ;
regV : (walk : Str) -> V ;
mkV2 : (look : V) -> (at : Str) -> V2 ;
dirV2 : (eat : V) -> V2 ;
--------------------------------------------
-- definitions, hidden from users
mkN x y = mkNoun x y ** {lock_CN = <>} ;
regN x = regNoun x ** {lock_CN = <>} ;
mkA x = ss x ** {lock_AP = <>} ;
mkV x y = mkVerb x y ** {lock_V = <>} ;
regV x = regVerb x ** {lock_V = <>} ;
mkV2 x p = x ** {c = p ; lock_V2 = <>} ;
dirV2 x = mkV2 x [] ;
}

View File

@@ -0,0 +1,4 @@
interface LexFoods = open Syntax in {
}

View File

@@ -0,0 +1,46 @@
--# -path=.:prelude
resource LexIta = open SyntaxIta, MorphoIta, Prelude in {
oper
-- constructors for genders
Gender : Type ;
masculine, feminine : Gender ;
-- constructors for open lexicon
mkN : Gender -> (vino,vini : Str) -> CN ;
regN : (vino : Str) -> CN ;
femN : CN -> CN ;
mkA : (nero,nera,neri,nere : Str) -> AP ;
regA : (nero : Str) -> AP ;
mkV : (ama,amano : Str) -> V ;
regV : (amare : Str) -> V ;
mkV2 : (aspettare : V) -> (a : Str) -> V2 ;
dirV2 : (mangiare : V) -> V2 ;
--------------------------------------------
-- definitions, hidden from users
Gender = MorphoIta.Gender ;
masculine = Masc ;
feminine = Fem ;
mkN g x y = mkNoun g x y ** {lock_CN = <>} ;
regN x = regNoun x ** {lock_CN = <>} ;
mkA x y z u = mkAdjective x y z u ** {lock_AP = <>} ;
regA x = regAdjective x ** {lock_AP = <>} ;
mkV x y = mkVerb x y ** {lock_V = <>} ;
regV x = regVerb x ** {lock_V = <>} ;
mkV2 x p = x ** {c = p ; lock_V2 = <>} ;
dirV2 x = mkV2 x [] ;
}

View File

@@ -0,0 +1,87 @@
--# -path=.:prelude
-- This is a simple Italian resource morphology for the GF tutorial.
resource MorphoIta = open Prelude in {
param
Number = Sg | Pl ;
Gender = Masc | Fem ;
oper
Noun : Type = {s : Number => Str ; g : Gender} ;
Adjective : Type = {s : Gender => Number => Str} ;
-- we will only use present indicative third person verb forms
Verb : Type = {s : Number => Str} ;
-- this function takes the gender and both singular and plural forms
mkNoun : Gender -> Str -> Str -> Noun = \g,vino,vini -> {
s = table {
Sg => vino ;
Pl => vini
} ;
g = g
} ;
-- this function takes the singular form
regNoun : Str -> Noun = \vino ->
let
vin = init vino ;
o = last vino
in
case o of {
"a" => mkNoun Fem vino (vin + "e") ; -- pizza
"o" | "e" => mkNoun Masc vino (vin + "i") ; -- vino, pane
_ => mkNoun Masc vino vino -- tram
} ;
-- to make nouns such as "carne", "università" feminine
femNoun : Noun -> Noun = \mano -> {
s = mano.s ;
g = Fem
} ;
-- this takes both genders and numbers
mkAdjective : (x1,_,_,x4 : Str) -> Adjective = \nero,nera,neri,nere -> {
s = table {
Masc => (mkNoun Masc nero neri).s ;
Fem => (mkNoun Fem nera nere).s
}
} ;
-- this takes the masculine singular form
regAdjective : Str -> Adjective = \nero ->
let ner = init nero in
case last nero of {
"o" => mkAdjective (ner + "o") (ner + "a") (ner + "i") (ner + "e") ;
"e" => mkAdjective (ner + "e") (ner + "e") (ner + "i") (ner + "i") ;
_ => mkAdjective nero nero nero nero
} ;
-- this function takes the singular and plural forms
mkVerb : Str -> Str -> Verb = \ama,amano -> {
s = table {
Sg => ama ;
Pl => amano
}
} ;
-- this function takes the infinitive form
regVerb : Str -> Verb = \amare ->
let am = Predef.tk 3 amare in
case Predef.dp 3 amare of {
"ere" => mkVerb (am + "e") (am + "ono") ; -- premere
"ire" => mkVerb (am + "isce") (am + "iscono") ; -- finire
_ => mkVerb (am + "a") (am + "ano") -- amare
} ;
}

View File

@@ -0,0 +1,46 @@
abstract Syntax = {
flags startcat=Phr ;
cat
S ; -- declarative sentence e.g. "this pizza is good"
NP ; -- noun phrase e.g. "this pizza"
CN ; -- common noun e.g. "pizza"
Det ; -- determiner e.g. "this"
AP ; -- adjectival phrase e.g. "very good"
AdA ; -- adadjective e.g. "very"
VP ; -- verb phrase e.g. "is good"
V ; -- intransitive verb e.g. "boil"
V2 ; -- two-place verb e.g. "eat"
fun
PosVP, NegVP : NP -> VP -> S ;
PredAP : AP -> VP ;
PredV : V -> VP ;
PredV2 : V2 -> NP -> VP ;
DetCN : Det -> CN -> NP ;
ModCN : AP -> CN -> CN ;
AdAP : AdA -> AP -> AP ;
-- entries of the closed lexicon
this_Det : Det ;
that_Det : Det ;
these_Det : Det ;
those_Det : Det ;
every_Det : Det ;
theSg_Det : Det ;
thePl_Det : Det ;
a_Det : Det ;
plur_Det : Det ;
two_Det : Det ;
very_AdA : AdA ;
too_AdA : AdA ;
}

View File

@@ -0,0 +1,67 @@
--# -path=.:prelude
concrete SyntaxEng of Syntax = open Prelude, MorphoEng in {
lincat
S = {s : Str} ;
NP = {s : Str ; n : Number} ;
CN = {s : Number => Str} ;
Det = {s : Str ; n : Number} ;
AP = {s : Str} ;
AdA = {s : Str} ;
VP = {s : Bool => Number => Str} ;
V = {s : Number => Str} ;
V2 = {s : Number => Str ; c : Str} ;
lin
PosVP np vp = {s = np.s ++ vp.s ! True ! np.n} ;
NegVP np vp = {s = np.s ++ vp.s ! False ! np.n} ;
PredAP ap = {s = \\b,n => copula b n ++ ap.s} ;
PredV v = {s = \\b,n => predVerb b n v} ;
PredV2 v2 np = {s = \\b,n => predVerb b n v2 ++ v2.c ++ np.s} ;
DetCN det cn = {s = det.s ++ cn.s ! det.n ; n = det.n} ;
ModCN ap cn = {s = \\n => ap.s ++ cn.s ! n} ;
AdAP ada ap = {s = ada.s ++ ap.s} ;
this_Det = {s = "this" ; n = Sg} ;
that_Det = {s = "that" ; n = Sg} ;
these_Det = {s = "these" ; n = Pl} ;
those_Det = {s = "those" ; n = Pl} ;
every_Det = {s = "every" ; n = Sg} ;
theSg_Det = {s = "the" ; n = Sg} ;
thePl_Det = {s = "the" ; n = Pl} ;
a_Det = {s = artIndef ; n = Sg} ;
plur_Det = {s = [] ; n = Pl} ;
two_Det = {s = "two" ; n = Pl} ;
very_AdA = {s = "very"} ;
too_AdA = {s = "too"} ;
oper
copula : Bool -> Number -> Str = \b,n -> case n of {
Sg => posneg b "is" ;
Pl => posneg b "are"
} ;
predVerb : Bool -> Number -> Verb -> Str = \b,n,verb ->
let inf = verb.s ! Sg in
case b of {
True => verb.s ! n ;
False => posneg b ((regVerb "do").s ! n) ++ inf
} ;
posneg : Bool -> Str -> Str = \b,do -> case b of {
True => do ;
False => do + "n't"
} ;
artIndef : Str =
pre {"a" ; "an" / strs {"a" ; "e" ; "i" ; "o"}} ;
}

View File

@@ -0,0 +1,81 @@
--# -path=.:prelude
concrete SyntaxIta of Syntax = open Prelude, MorphoIta in {
lincat
S = {s : Str} ;
NP = {s : Str ; g : Gender ; n : Number} ;
CN = {s : Number => Str ; g : Gender} ;
Det = {s : Gender => Str ; n : Number} ;
AP = {s : Gender => Number => Str} ;
AdA = {s : Str} ;
VP = {s : Bool => Gender => Number => Str} ;
V = {s : Number => Str} ;
V2 = {s : Number => Str ; c : Str} ;
lin
PosVP np vp = {s = np.s ++ vp.s ! True ! np.g ! np.n} ;
NegVP np vp = {s = np.s ++ vp.s ! False ! np.g ! np.n} ;
PredAP ap = {s = \\b,g,n => posneg b ++ copula n ++ ap.s ! g ! n} ;
PredV v = {s = \\b,_,n => posneg b ++ v.s ! n} ;
PredV2 v2 np = {s = \\b,_,n => posneg b ++ v2.s ! n ++ v2.c ++ np.s} ;
DetCN det cn = {s = det.s ! cn.g ++ cn.s ! det.n ; g = cn.g ; n = det.n} ;
ModCN ap cn = {s = \\n => cn.s ! n ++ ap.s ! cn.g ! n ; g = cn.g} ;
AdAP ada ap = {s = \\n,g => ada.s ++ ap.s ! n ! g} ;
this_Det = mkDet Sg (regAdjective "questo") ;
that_Det = mkDet Sg (regAdjective "quello") ;
these_Det = mkDet Pl (regAdjective "questo") ;
those_Det = mkDet Pl (regAdjective "quello") ;
every_Det = {s = \\_ => "ogni" ; n = Sg} ;
theSg_Det = {s = artDef Sg ; n = Sg} ;
thePl_Det = {s = artDef Pl ; n = Pl} ;
a_Det = {s = artIndef ; n = Pl} ;
plur_Det = {s = \\_ => [] ; n = Pl} ;
two_Det = {s = \\_ => "due" ; n = Pl} ;
very_AdA = {s = "molto"} ;
too_AdA = {s = "troppo"} ;
oper
copula : Number -> Str = \n -> case n of {
Sg => "è" ;
Pl => "sono"
} ;
posneg : Bool -> Str = \b -> case b of {
True => [] ;
False => "non"
} ;
mkDet : Number -> Adjective -> Det = \n,adj -> {
s = \\g => adj.s ! g ! n ;
n = n ;
lock_Det = <>
} ;
artDef : Number -> Gender => Str = \n -> case n of {
Sg => table {
Masc => pre {"il" ; "lo" / sImpuro} ;
Fem => "la"
} ;
Pl => table {
Masc => pre {"i" ; "gli" / sImpuro ; "gli" / vowel} ;
Fem => "le"
}
} ;
artIndef : Gender => Str = table {
Masc => pre {"un" ; "uno" / sImpuro} ;
Fem => pre {"una" ; "un'" / vowel}
} ;
sImpuro : Strs = strs {"sb" ; "sp" ; "sy" ; "z"} ;
vowel : Strs = strs {"a" ; "e" ; "i" ; "o" ; "u"} ;
}