prepared mini syntax example

This commit is contained in:
aarne
2007-08-16 09:41:00 +00:00
parent 09e69820b4
commit 912cbb3bf3
8 changed files with 421 additions and 299 deletions

View File

@@ -1,4 +1,4 @@
Grammatical Framework: A Framework for Multilingual Natural Language Applications
Grammatical Framework: Tutorial, Advanced Applications, and Reference Manual
Author: Aarne Ranta aarne (at) cs.chalmers.se
Last update: %%date(%c)
@@ -1768,6 +1768,43 @@ concrete FoodsEng of Foods = open Prelude, MorphoEng in {
```
==Pattern matching==
We have so far built all expressions of the ``table`` form
from branches whose patterns are constants introduced in
``param`` definitions, as well as constant strings.
But there are more expressive patterns. Here is a summary of the possible forms:
- a constructor pattern (identifier introduced in a ``param`` definition) matches
the identical constructor
- a variable pattern (identifier other than constant parameter) matches anything
- the wild card ``_`` matches anything
- a string literal pattern, e.g. ``"s"``, matches the same string
- a disjunctive pattern ``P | ... | Q`` matches anything that
one of the disjuncts matches
Pattern matching is performed in the order in which the branches
appear in the table: the branch of the first matching pattern is followed.
As a first example, let us take an English noun that has the same form in
singular and plura:
```
lin Fish = {s = table {_ => "fish"}} ;
```
As syntactic sugar, one-branch tables can be written concisely,
```
\\P,...,Q => t === table {P => ... table {Q => t} ...}
```
Thus we could rewrite the above rule
```
lin Fish = {s = \\_ => "fish"} ;
```
Finally, the ``case`` expressions common in functional
programming languages are syntactic sugar for table selections:
```
case e of {...} === table {...} ! e
```
%--!
==Hierarchic parameter types==
@@ -1854,17 +1891,211 @@ are not a good idea in top-level categories accessed by the users
of a grammar application.
==More constructs for concrete syntax==
In this section, we go through constructs that are not necessary
in simple grammars or when the concrete syntax relies on libraries.
But they are useful when writing advanced concrete syntax implementations,
such as resource grammar libraries. Moreover, they conclude
the presentation of concrete syntax constructs.
%--!
===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
} ;
```
===Record extension and subtyping===
Record types and records can be **extended** with new fields. For instance,
in German it is natural to see transitive verbs as verbs with a case.
The symbol ``**`` is used for both constructs.
```
lincat TV = Verb ** {c : Case} ;
lin Follow = regVerb "folgen" ** {c = Dative} ;
```
To extend a record type or a record with a field whose label it
already has is a type error.
A record type //T// is a **subtype** of another one //R//, if //T// has
all the fields of //R// and possibly other fields. For instance,
an extension of a record type is always a subtype of it.
If //T// is a subtype of //R//, an object of //T// can be used whenever
an object of //R// is required. For instance, a transitive verb can
be used whenever a verb is required.
**Contravariance** means that a function taking an //R// as argument
can also be applied to any object of a subtype //T//.
===Tuples and product types===
Product types and tuples are syntactic sugar for record types and records:
```
T1 * ... * Tn === {p1 : T1 ; ... ; pn : Tn}
<t1, ..., tn> === {p1 = T1 ; ... ; pn = Tn}
```
Thus the labels ``p1, p2,...`` are hard-coded.
===Record and tuple patterns===
Record types of parameter types also count as parameter types.
A typical example is a record of agreement features, e.g. French
```
oper Agr : PType = {g : Gender ; n : Number ; p : Person} ;
```
Notice the term ``PType`` rather than just ``Type`` referring to
parameter types. Every ``PType`` is also a ``Type``, but not vice-versa.
Pattern matching is done in the expected way, but it can moreover
utilize partial records: the branch
```
{g = Fem} => t
```
in a table of type ``Agr => T`` means the same as
```
{g = Fem ; n = _ ; p = _} => t
```
Tuple patterns are translated to record patterns in the
same way as tuples to records; partial patterns make it
possible to write, slightly surprisingly,
```
case <g,n,p> of {
<Fem> => t
...
}
```
===Free variation===
Sometimes there are many alternative ways to define a concrete syntax.
For instance, the verb negation in English can be expressed both by
//does not// and //doesn't//. In linguistic terms, these expressions
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 ! Pl} ;
```
An empty variant list
```
variants {}
```
can be used e.g. if a word lacks a certain form.
In general, ``variants`` should be used cautiously. It is not
recommended for modules aimed to be libraries, because the
user of the library has no way to choose among the variants.
%--!
===Prefix-dependent choices===
Sometimes a token has different forms depending on the token
that follows. An example is the English indefinite article,
which is //an// if a vowel follows, //a// otherwise.
Which form is chosen can only be decided at run time, i.e.
when a string is actually build. GF has a special construct for
such tokens, the ``pre`` construct exemplified in
```
oper artIndef : Str =
pre {"a" ; "an" / strs {"a" ; "e" ; "i" ; "o"}} ;
```
Thus
```
artIndef ++ "cheese" ---> "a" ++ "cheese"
artIndef ++ "apple" ---> "an" ++ "apple"
```
This very example does not work in all situations: the prefix
//u// has no general rules, and some problematic words are
//euphemism, one-eyed, n-gram//. It is possible to write
```
oper artIndef : Str =
pre {"a" ;
"a" / strs {"eu" ; "one"} ;
"an" / strs {"a" ; "e" ; "i" ; "o" ; "n-"}
} ;
```
===Predefined types===
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"
```
The objects of each of these categories are **literals**
as indicated in the comments above. No ``fun`` definition
can have a predefined category as its value type, but
they can be used as arguments. For example:
```
fun StreetAddress : Int -> String -> Address ;
lin StreetAddress number street = {s = number.s ++ street.s} ;
-- e.g. (StreetAddress 10 "Downing Street") : Address
```
FIXME: The linearization type is ``{s : Str}`` for all these categories.
===Overloading of operations===
Large libraries, such as the GF Resource Grammar Library, may define
hundreds of names, which can be unpractical
for both the library writer and the user. The writer has to invent longer
and longer names which are not always intuitive,
and the user has to learn or at least be able to find all these names.
A solution to this problem, adopted by languages such as C++, is **overloading**:
the same name can be used for several functions. When such a name is used, the
compiler performs **overload resolution** to find out which of the possible functions
is meant. The resolution is based on the types of the functions: all functions that
have the same name must have different types.
In C++, functions with the same name can be scattered everywhere in the program.
In GF, they must be grouped together in ``overload`` groups. Here is an example
of an overload group, defining four ways to define nouns in Italian:
```
oper mkN = overload {
mkN : Str -> N = -- regular nouns
mkN : Str -> Gender -> N = -- regular nouns with unexpected gender
mkN : Str -> Str -> N = -- irregular nouns
mkN : Str -> Str -> Gender -> N = -- irregular nouns with unexpected gender
}
```
All of the following uses of ``mkN`` are easy to resolve:
```
lin Pizza = mkN "pizza" ; -- Str -> N
lin Hand = mkN "mano" Fem ; -- Str -> Gender -> N
lin Man = mkN "uomo" "uomini" ; -- Str -> Str -> N
```
=Implementing morphology=
=Implementing morphology and syntax=
==Worst-case functions and data abstraction==
@@ -1952,33 +2183,6 @@ without explicit ``open`` of the module ``Predef``.
%--!
==Pattern matching==
We have so far built all expressions of the ``table`` form
from branches whose patterns are constants introduced in
``param`` definitions, as well as constant strings.
But there are more expressive patterns. Here is a summary of the possible forms:
- a variable pattern (identifier other than constant parameter) matches anything
- the wild card ``_`` matches anything
- a string literal pattern, e.g. ``"s"``, matches the same string
- a disjunctive pattern ``P | ... | Q`` matches anything that
one of the disjuncts matches
Pattern matching is performed in the order in which the branches
appear in the table: the branch of the first matching pattern is followed.
As syntactic sugar, one-branch tables can be written concisely,
```
\\P,...,Q => t === table {P => ... table {Q => t} ...}
```
Finally, the ``case`` expressions common in functional
programming languages are syntactic sugar for table selections:
```
case e of {...} === table {...} ! e
```
%--!
==An intelligent noun paradigm using pattern matching==
@@ -2059,23 +2263,9 @@ unstressed pre-final vowel //e// disappears in the plural
bil => bil + "ar"
} ;
```
Semantics: variables are always bound to the **first match**, which is the first
in the sequence of binding lists ``Match p v`` defined as follows. In the definition,
``p`` is a pattern and ``v`` is a value. The semantics is given in Haskell notation.
```
Match (p1|p2) v = Match p1 ++ U Match p2 v
Match (p1+p2) s = [Match p1 s1 ++ Match p2 s2 |
i <- [0..length s], (s1,s2) = splitAt i s]
Match p* s = [[]] if Match "" s ++ Match p s ++ Match (p+p) s ++... /= []
Match -p v = [[]] if Match p v = []
Match c v = [[]] if c == v -- for constant and literal patterns c
Match x v = [[(x,v)]] -- for variable patterns x
Match x@p v = [[(x,v)]] + M if M = Match p v /= []
Match p v = [] otherwise -- failure
```
Examples:
Variables in regular expression patterns
are always bound to the **first match**, which is the first
in the sequence of binding lists. For example:
- ``x + "e" + y`` matches ``"peter"`` with ``x = "p", y = "ter"``
- ``x + "er"*`` matches ``"burgerer"`` with ``x = "burg"
@@ -2180,223 +2370,15 @@ The ``number`` flag gives the number of exercises generated.
%--!
=More constructs for concrete syntax=
In this chapter, we go through constructs that are not necessary in simple grammars
or when the concrete syntax relies on libraries. But they are useful when
writing advanced concrete syntax implementations, such as resource grammar libraries.
This chapter can safely be skipped if the reader prefers to continue to the
chapter on using libraries.
%--!
==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
} ;
```
==Record extension and subtyping==
Record types and records can be **extended** with new fields. For instance,
in German it is natural to see transitive verbs as verbs with a case.
The symbol ``**`` is used for both constructs.
```
lincat TV = Verb ** {c : Case} ;
lin Follow = regVerb "folgen" ** {c = Dative} ;
```
To extend a record type or a record with a field whose label it
already has is a type error.
A record type //T// is a **subtype** of another one //R//, if //T// has
all the fields of //R// and possibly other fields. For instance,
an extension of a record type is always a subtype of it.
If //T// is a subtype of //R//, an object of //T// can be used whenever
an object of //R// is required. For instance, a transitive verb can
be used whenever a verb is required.
**Contravariance** means that a function taking an //R// as argument
can also be applied to any object of a subtype //T//.
==Tuples and product types==
Product types and tuples are syntactic sugar for record types and records:
```
T1 * ... * Tn === {p1 : T1 ; ... ; pn : Tn}
<t1, ..., tn> === {p1 = T1 ; ... ; pn = Tn}
```
Thus the labels ``p1, p2,...`` are hard-coded.
==Record and tuple patterns==
Record types of parameter types are also parameter types.
A typical example is a record of agreement features, e.g. French
```
oper Agr : PType = {g : Gender ; n : Number ; p : Person} ;
```
Notice the term ``PType`` rather than just ``Type`` referring to
parameter types. Every ``PType`` is also a ``Type``, but not vice-versa.
Pattern matching is done in the expected way, but it can moreover
utilize partial records: the branch
```
{g = Fem} => t
```
in a table of type ``Agr => T`` means the same as
```
{g = Fem ; n = _ ; p = _} => t
```
Tuple patterns are translated to record patterns in the
same way as tuples to records; partial patterns make it
possible to write, slightly surprisingly,
```
case <g,n,p> of {
<Fem> => t
...
}
```
==Free variation==
Sometimes there are many alternative ways to define a concrete syntax.
For instance, the verb negation in English can be expressed both by
//does not// and //doesn't//. In linguistic terms, these expressions
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 ! Pl} ;
```
An empty variant list
```
variants {}
```
can be used e.g. if a word lacks a certain form.
In general, ``variants`` should be used cautiously. It is not
recommended for modules aimed to be libraries, because the
user of the library has no way to choose among the variants.
%--!
==Prefix-dependent choices==
Sometimes a token has different forms depending on the token
that follows. An example is the English indefinite article,
which is //an// if a vowel follows, //a// otherwise.
Which form is chosen can only be decided at run time, i.e.
when a string is actually build. GF has a special construct for
such tokens, the ``pre`` construct exemplified in
```
oper artIndef : Str =
pre {"a" ; "an" / strs {"a" ; "e" ; "i" ; "o"}} ;
```
Thus
```
artIndef ++ "cheese" ---> "a" ++ "cheese"
artIndef ++ "apple" ---> "an" ++ "apple"
```
This very example does not work in all situations: the prefix
//u// has no general rules, and some problematic words are
//euphemism, one-eyed, n-gram//. It is possible to write
```
oper artIndef : Str =
pre {"a" ;
"a" / strs {"eu" ; "one"} ;
"an" / strs {"a" ; "e" ; "i" ; "o" ; "n-"}
} ;
```
==Predefined types==
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"
```
The objects of each of these categories are **literals**
as indicated in the comments above. No ``fun`` definition
can have a predefined category as its value type, but
they can be used as arguments. For example:
```
fun StreetAddress : Int -> String -> Address ;
lin StreetAddress number street = {s = number.s ++ street.s} ;
-- e.g. (StreetAddress 10 "Downing Street") : Address
```
FIXME: The linearization type is ``{s : Str}`` for all these categories.
==Overloading of operations==
Large libraries, such as the GF Resource Grammar Library, may define
hundreds of names, which can be unpractical
for both the library writer and the user. The writer has to invent longer
and longer names which are not always intuitive,
and the user has to learn or at least be able to find all these names.
A solution to this problem, adopted by languages such as C++, is **overloading**:
the same name can be used for several functions. When such a name is used, the
compiler performs **overload resolution** to find out which of the possible functions
is meant. The resolution is based on the types of the functions: all functions that
have the same name must have different types.
In C++, functions with the same name can be scattered everywhere in the program.
In GF, they must be grouped together in ``overload`` groups. Here is an example
of an overload group, defining four ways to define nouns in Italian:
```
oper mkN = overload {
mkN : Str -> N = -- regular nouns
mkN : Str -> Gender -> N = -- regular nouns with unexpected gender
mkN : Str -> Str -> N = -- irregular nouns
mkN : Str -> Str -> Gender -> N = -- irregular nouns with unexpected gender
}
```
All of the following uses of ``mkN`` are easy to resolve:
```
lin Pizza = mkN "pizza" ; -- Str -> N
lin Hand = mkN "mano" Fem ; -- Str -> Gender -> N
lin Man = mkN "uomo" "uomini" ; -- Str -> Str -> N
```
%--!
=Using the resource grammar library=
In this chapter, we will take a look at the GF resource grammar library.
We will use the library to implement a slightly extended ``Food`` grammar
and port it to some new languages.
**Exercise**. Define the mini resource of the previous chapter by
using a functor over the full resource.
==The coverage of the library==

View File

@@ -8,6 +8,9 @@ resource MorphoEng = open Prelude in {
oper
Noun, Verb : Type = {s : Number => Str} ;
NP = {s : Str ; n : Number} ;
VP = {s : Bool => Bool => Number => Str * Str} ; -- decl, pol
mkNoun : Str -> Str -> Noun = \x,y -> {
s = table {
Sg => x ;

View File

@@ -3,22 +3,33 @@ abstract Syntax = {
flags startcat=Phr ;
cat
Phr ; -- any complete sentence e.g. "Is this pizza good?"
S ; -- declarative sentence e.g. "this pizza is good"
QS ; -- question sentence e.g. "is this pizza good"
NP ; -- noun phrase e.g. "this pizza"
CN ; -- common noun e.g. "pizza"
IP ; -- interrogative phrase e.g "which pizza"
CN ; -- common noun phrase e.g. "very good 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"
N ; -- noun e.g. "pizza"
A ; -- adjective e.g. "good"
V ; -- intransitive verb e.g. "boil"
V2 ; -- two-place verb e.g. "eat"
fun
PhrS : S -> Phr ;
PhrQS : QS -> Phr ;
PosVP, NegVP : NP -> VP -> S ;
QPosVP, QNegVP : NP -> VP -> QS ;
IPPosVP, IPNegVP : IP -> VP -> QS ;
IPPosV2, IPNegV2 : IP -> NP -> V2 -> QS ;
PredAP : AP -> VP ;
PredV : V -> VP ;
PredV2 : V2 -> NP -> VP ;
ComplV2 : V2 -> NP -> VP ;
ComplAP : AP -> VP ;
DetCN : Det -> CN -> NP ;
@@ -26,6 +37,11 @@ abstract Syntax = {
AdAP : AdA -> AP -> AP ;
WhichCN : CN -> IP ;
UseN : N -> CN ;
UseA : A -> AP ;
UseV : V -> VP ;
-- entries of the closed lexicon
@@ -36,11 +52,9 @@ abstract Syntax = {
every_Det : Det ;
theSg_Det : Det ;
thePl_Det : Det ;
a_Det : Det ;
indef_Det : Det ;
plur_Det : Det ;
two_Det : Det ;
very_AdA : AdA ;
too_AdA : AdA ;
}
}

View File

@@ -3,23 +3,53 @@
concrete SyntaxEng of Syntax = open Prelude, MorphoEng in {
lincat
Phr = {s : Str} ;
S = {s : Str} ;
NP = {s : Str ; n : Number} ;
CN = {s : Number => Str} ;
QS = {s : Str} ;
NP = MorphoEng.NP ;
IP = MorphoEng.NP ;
CN = Noun ;
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} ;
VP = MorphoEng.VP ;
N = Noun ;
A = {s : Str} ;
V = Verb ;
V2 = Verb ** {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} ;
PhrS = postfixSS "." ;
PhrQS = postfixSS "?" ;
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} ;
PosVP = predVP True True ;
NegVP = predVP True False ;
QPosVP = predVP False True ;
QNegVP = predVP False False ;
IPPosVP = predVP True True ;
IPNegVP = predVP True False ;
IPPosV2 ip np v2 = {
s = let
vp : MorphoEng.VP = {s = \\q,b,n => predVerb v2 q b n} ;
in
bothWays (ip.s ++ (predVP False True np vp).s) v2.c
} ;
IPNegV2 ip np v2 = {
s = let
vp : MorphoEng.VP = {s = \\q,b,n => predVerb v2 q b n} ;
in
bothWays (ip.s ++ (predVP False False np vp).s) v2.c
} ;
ComplV2 v2 np = {
s = \\q,b,n =>
let vp = predVerb v2 q b n in
<vp.p1, vp.p2 ++ v2.c ++ np.s>
} ;
ComplAP ap = {s = \\_,b,n => <copula b n, ap.s>} ;
DetCN det cn = {s = det.s ++ cn.s ! det.n ; n = det.n} ;
@@ -27,6 +57,12 @@ concrete SyntaxEng of Syntax = open Prelude, MorphoEng in {
AdAP ada ap = {s = ada.s ++ ap.s} ;
WhichCN cn = {s = "which" ++ cn.s ! Sg ; n = Sg} ;
UseN n = n ;
UseA a = a ;
UseV v = {s = \\q,b,n => predVerb v q b n} ;
this_Det = {s = "this" ; n = Sg} ;
that_Det = {s = "that" ; n = Sg} ;
these_Det = {s = "these" ; n = Pl} ;
@@ -34,25 +70,39 @@ concrete SyntaxEng of Syntax = open Prelude, MorphoEng in {
every_Det = {s = "every" ; n = Sg} ;
theSg_Det = {s = "the" ; n = Sg} ;
thePl_Det = {s = "the" ; n = Pl} ;
a_Det = {s = artIndef ; n = Sg} ;
indef_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
predVP : Bool -> Bool -> MorphoEng.NP -> MorphoEng.VP -> SS =
\q,b,np,vp -> {
s = let vps = vp.s ! q ! b ! np.n
in case q of {
True => np.s ++ vps.p1 ++ vps.p2 ;
False => vps.p1 ++ np.s ++ vps.p2
}
} ;
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
do : Bool -> Number -> Str = \b,n ->
posneg b ((regVerb "do").s ! n) ;
predVerb : Verb -> Bool -> Bool -> Number -> Str * Str = \verb,q,b,n ->
let
inf = verb.s ! Pl ;
fin = verb.s ! n ;
aux = do b n
in
case <q,b> of {
<True,True> => <[],fin> ;
_ => <aux,inf>
} ;
posneg : Bool -> Str -> Str = \b,do -> case b of {
@@ -62,6 +112,4 @@ concrete SyntaxEng of Syntax = open Prelude, MorphoEng in {
artIndef : Str =
pre {"a" ; "an" / strs {"a" ; "e" ; "i" ; "o"}} ;
}

View File

@@ -3,23 +3,38 @@
concrete SyntaxIta of Syntax = open Prelude, MorphoIta in {
lincat
Phr = {s : Str} ;
S = {s : Str} ;
QS = {s : Str} ;
NP = {s : Str ; g : Gender ; n : Number} ;
IP = {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} ;
N = {s : Number => Str ; g : Gender} ;
A = {s : 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} ;
PhrS = postfixSS "." ;
PhrQS = postfixSS "?" ;
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} ;
QPosVP np vp = {s = np.s ++ vp.s ! True ! np.g ! np.n} ;
QNegVP np vp = {s = np.s ++ vp.s ! False ! np.g ! np.n} ;
IPPosVP np vp = {s = np.s ++ vp.s ! True ! np.g ! np.n} ;
IPNegVP np vp = {s = np.s ++ vp.s ! False ! np.g ! np.n} ;
IPPosV2 ip np v2 = {s = v2.c ++ ip.s ++ v2.s ! np.n ++ np.s} ;
IPNegV2 ip np v2 = {s = v2.c ++ ip.s ++ "non" ++ v2.s ! np.n ++ np.s} ;
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} ;
ComplV2 v2 np = {s = \\b,_,n => posneg b ++ v2.s ! n ++ v2.c ++ np.s} ;
ComplAP ap = {s = \\b,g,n => posneg b ++ copula n ++ ap.s ! g ! n} ;
DetCN det cn = {s = det.s ! cn.g ++ cn.s ! det.n ; g = cn.g ; n = det.n} ;
@@ -27,6 +42,13 @@ concrete SyntaxIta of Syntax = open Prelude, MorphoIta in {
AdAP ada ap = {s = \\n,g => ada.s ++ ap.s ! n ! g} ;
WhichCN cn = {s = "quale" ++ cn.s ! Sg ; g = cn.g ; n = Sg} ;
UseN n = n ;
UseA a = a ;
UseV v = {s = \\b,_,n => posneg b ++ v.s ! n} ;
this_Det = mkDet Sg (regAdjective "questo") ;
that_Det = mkDet Sg (regAdjective "quello") ;
these_Det = mkDet Pl (regAdjective "questo") ;
@@ -34,17 +56,16 @@ concrete SyntaxIta of Syntax = open Prelude, MorphoIta in {
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} ;
indef_Det = {s = artIndef ; n = Sg} ;
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 => "è" ;
Sg => "è" ;
Pl => "sono"
} ;

View File

@@ -0,0 +1,8 @@
abstract Test = Syntax ** {
fun
Wine, Cheese, Fish, Pizza, Waiter, Customer : N ;
Fresh, Warm, Italian, Expensive, Delicious, Boring : A ;
Stink : V ;
Eat, Love, Talk : V2 ;
}

View File

@@ -0,0 +1,23 @@
--# -path=.:resource:prelude
concrete TestEng of Test = SyntaxEng ** open Prelude, MorphoEng in {
lin
Wine = regNoun "wine" ;
Cheese = regNoun "cheese" ;
Fish = mkNoun "fish" "fish" ;
Pizza = regNoun "pizza" ;
Waiter = regNoun "waiter" ;
Customer = regNoun "customer" ;
Fresh = ss "fresh" ;
Warm = ss "warm" ;
Italian = ss "Italian" ;
Expensive = ss "expensive" ;
Delicious = ss "delicious" ;
Boring = ss "boring" ;
Stink = regVerb "stink" ;
Eat = regVerb "eat" ** {c = []} ;
Love = regVerb "love" ** {c = []} ;
Talk = regVerb "talk" ** {c = "about"} ;
}

View File

@@ -0,0 +1,23 @@
--# -path=.:resource:prelude
concrete TestIta of Test = SyntaxIta ** open Prelude, MorphoIta in {
lin
Wine = regNoun "vino" ;
Cheese = regNoun "formaggio" ;
Fish = regNoun "pesce" ;
Pizza = regNoun "pizza" ;
Waiter = regNoun "cameriere" ;
Customer = regNoun "cliente" ;
Fresh = regAdjective "fresco" ;
Warm = regAdjective "caldo" ;
Italian = regAdjective "italiano" ;
Expensive = regAdjective "caro" ;
Delicious = regAdjective "delizioso" ;
Boring = regAdjective "noioso" ;
Stink = regVerb "puzzare" ;
Eat = regVerb "mangiare" ** {c = []} ;
Love = regVerb "amare" ** {c = []} ;
Talk = regVerb "parlare" ** {c = "di"} ;
}