# GF Resources for Swedish

Språkdata Seminar, Gothenburg, 1 March 2005

Aarne Ranta

`aarne@cs.chalmers.se`

## Plan

Introduction to resource grammars

Swedish morphology and lexicon in GF

Syntax case study: Swedish determiners

Syntax case study: Swedish sentence structure

Danish and Norwegian through parametrization

## GF = Grammatical Framework

A grammar formalism based on functional programming and type theory.

Designed to be nice for ordinary programmers to use.

Mission: to make natural-language applications available for ordinary programmers, in tasks like

- software documentation
- domain-specific translation
- human-computer interaction
- dialogue systems

Thus not primarily another theoretical framework for linguists.

## Multilingual grammars

Abstract syntax: language-independent representation

      cat Prop ; Nat ;
      fun Even : Nat -> Prop ;

Concrete syntax: mapping from abstract syntax trees to strings in a language (English, French, German, Swedish,...)

      lin Even x = {s = x.s ++ "is" ++ "even"} ;

      lin Even x = {s = x.s ++ "est" ++ "pair"} ;

      lin Even x = {s = x.s ++ "ist" ++ "gerade"} ;

      lin Even x = {s = x.s ++ "är" ++ "jämnt"} ;

We can translate between language via the abstract syntax.

Is it really so simple?

## Difficulties with concrete syntax

Most languages have rules of inflection, agreement, and word order, which have to be obeyed when putting together expressions.

The previous multilingual grammar breaks these rules in many situations:

2 and 3 is even
la somme de 3 et de 5 est pair
wenn 2 ist gerade, dann 2+2 ist gerade
om 2 är jämnt, 2+2 är jämnt

## Solving the difficulties

GF has tools for expressing the linguistic rules that are needed to produce correct translations in different languages.

Instead of just strings, we need

parameters, tables, and record types. For instance, French:

      param Mod = Ind | Subj ;
      param Gen = Masc | Fem ;

      lincat Nat = {s : Str ; g : Gen} ;
      lincat Prop = {s : Mod => Str} ;

      lin Even x = {s =
          table {
            m => x.s ++
                 case m   of {Ind  => "est" ;  Subj => "soit"} ++
                 case x.g of {Masc => "pair" ; Fem  => "paire"}
          }
        } ;

## Language + Libraries

Writing natural language grammars still requires theoretical knowledge about the language.

Which kind of a programmer is easier to find?

- one who can write a sorting algorithm
- one who can write a grammar for Swedish determiners

In main-stream programming, sorting algorithms are not written by hand but taken from libraries.

In the same way, we want to create grammar libraries that encapsulate basic linguistic facts.

Cf. the Java success story: the language is just a half of the success - libraries are another half.

## Example of library-based grammar writing

To define a Swedish expression of a mathematical predicate from scratch:

      Even x =
        let jämn = case <x.n,x.g> of {
          <Sg,Utr>   => "jämn" ;
          <Sg,Neutr> => "jämnt" ;
          <Pl,_>     => "jämna"
          }
        in
        {s = table {
          Main => x.s ! Nom ++ "är" ++ jämn ;
          Inv  => "är" ++ x.s ! Nom ++ jämn ;
          Sub  => x.s ! Nom ++ "är" ++ jämn
          }
        }

To use library functions for syntax and morphology:

      Even = predA (regA "jämn") ;

## Questions in grammar library design

What should there be in the library?
- morphology, lexicon, syntax, semantics,...

  How do we organize and present the library?

- division into modules, level of granularity
- "school grammar" vs. sophisticated linguistic concepts

  Where do we get the data from?

- automatic extraction or hand-writing?
- reuse of existing resources?

  Extra constraint: we want open-source free software.

  ## The scope of the resource grammar library

  All morphological paradigms

  Basic lexicon of structural, common, and irregular words

  Basic syntactic structures

  Currently,

- no semantics,
- no language-specific structures if not necessary for expressivity.

  ## Success criteria

  Grammatical correctness

  Semantic coverage: you can express whatever you want.

  Usability as library for non-linguists.

  (Bonus for linguists:) nice generalizations w.r.t. language families, using the module system of GF.

  ## These are not our success criteria

  Language coverage: you can parse all expressions. Example: the French passé simple tense, although covered by the morhology, is not used in the language-independent API, but only the passé composé is.

  Semantic correctness

        colourless green ideas sleep furiously

        the time is seventy past forty-two

  (Warning for linguists:) theoretical innovation in syntax (and it will all be hidden anyway!)

  ## So where is semantics?

  GF incorporates a Logical Framework and is therefore capable of expressing logical semantics ā la Montague or any other flavour, including anaphora and discourse.

  But we do not try to give semantics once and for all for the whole language.

  Instead, we expect semantics to be given in application grammars built on semantic models of different domains.

  Example application: number theory

        fun Even : Nat -> Prop ;         -- a mathematical predicate

        lin Even = predA (regA "even") ; -- English translation
        lin Even = predA (regA "pair") ; -- French translation
        lin Even = predA (regA "jämn") ; -- Swedish translation

  How could the resource predict that just these translations are correct in this domain?

  ## Languages

  The current GF Resource Project covers ten languages:
  - `Dan`ish
  - `Eng`lish
  - `Fin`nish
  - `Fre`nch
  - `Ger`man
  - `Ita`lian
  - `Nor`wegian
  - `Rus`sian
  - `Spa`nish
  - `Swe`dish
  The first three letters (`Dan` etc) are used in grammar module names

  ## Library structure 1: language-independent API

- syntactic `Categories` (parts of speech, word classes)

- `Rules` for combining words and phrases, e.g.

- the most common `Structural` words (determiners, conjunctions, pronouns), e.g.

  ## Library structure 2: language-dependent modules

- morphological `Paradigms`, e.g.

- `Lexicon` of frequent words

- `Ext`ended syntax with language-specific rules

  ## How much can be language-independent?

  For the ten languages we have considered, it is possible to implement the current API.

  Reservations:

  - does not necessarily extend to all other languages
  - does not necessarily cover the most idiomatic expressions of each language
  - may not be the easiest API to implement (e.g. negation and inversion with do in English suggest that some other structure would be more natural)
  - does not guarantee that same structure has the same semantics in different languages

    ## Swedish morphology and lexicon

    Lexicon: list of words with inflection and other morphological information (gender of nouns etc).

    Paradigms: set of functions for extending the lexicon.

    ### Parts of speech

    A word class is a record type, with parametric and inherent features (`param`eters). For example, nouns are the type

          N = {s : Number => Species => Case => Str ; g : Gender} ;

    where

          param
            Species = Indef | Def ;
            Number  = Sg | Pl ;
            Case    = Nom | Gen ;

    ### Defining a lexical unit

    Every lexical unit has a word class as its type. The type checker of GF verifies that all and only the relevant information of the unit is given. For instance, an entry for the noun bil ("car") looks as follows.

          bil =
          {s = table {
             Sg => table {
               Indef => table {Nom => "bil"     ; Gen => "bils" } ;
               Def   => table {Nom => "bilen"   ; Gen => "bilens" }
               } ;
             Pl => table {
               Indef => table {Nom => "bilar"   ; Gen => "bilars" } ;
               Def   => table {Nom => "bilarna" ; Gen => "bilarnas" }
               }
             } ;
           g = Utr
          }

    ### The Golden Rule of Functional Programming

    Whenever you find yourself programming by "copy and paste", write a function instead.

    Thus do not write

          gran =
          {s = table {
             Sg => table {
               Indef => table {Nom => "gran"     ; Gen => "grans" } ;
               Def   => table {Nom => "granen"   ; Gen => "granens" }
               } ;
             Pl => table {
               Indef => table {Nom => "granar"   ; Gen => "granars" } ;
               Def   => table {Nom => "granarna" ; Gen => "granarnas" }
               }
             } ;
           g = Utr
          }

    ### Inflectional paradigms as functions

    Instead, write a paradigm that can be applied to any word that is "inflected in the same way":

          decl2 : Str -> N = \bil ->
          {s = table {
             Sg => table {
               Indef => table {Nom => bil + ""     ; Gen => bil + "s" } ;
               Def   => table {Nom => bil + "en"   ; Gen => bil + "ens" }
               } ;
             Pl => table {
               Indef => table {Nom => bil + "ar"   ; Gen => bil + "ars" } ;
               Def   => table {Nom => bil + "arna" ; Gen => bil + "arnas" }
               }
             } ;
           g = Utr
          }

    This function can be used over and over again:

          bil  = decl2 "bil" ;
          gran = decl2 "gran" ;
          dag  = decl2 "dag" ;

    ### High-level definition of paradigms

    Recall: functions instead of copy-and-paste!

    First define (for each word class) a worst-case function:

          mkN : (apa,apan,apor,aporna : Str) -> Noun =
          {s = table {
             Sg => table {
               Indef => mkCase apa ;
               Def   => mkCase apan
               } ;
             Pl => table {
               Indef => mkCase apor ;
               Def   => mkCase aporna
               }
             } ;
           g = case last apan of {
                 "n" => Utr ;
                 _   => Neutr
          }

    where we uniformly produce the genitive by

          mkCase : Str -> Case => Str = \f -> table {
              Nom => f ;
              Gen => f + case last f of {
                "s" | "x" => [] ;
                _ => "s"
                }
              } ;

    ### High-level definition of paradigms

    Then define, for instance, the five declensions as follows:

          decl1 : Str -> N = \apa -> let ap = init apa in
            mkN apa (apa + "n") (ap + "or") (ap + "orna") ;

          decl2 : Str -> N = \bil ->
            mkN bil (bil + "en") (bil + "ar") (bil + "arna") ;

          decl3 : Str -> N = \fil ->
            mkN fil (fil + "en") (fil + "er") (fil + "erna") ;

          decl4 : Str -> N = \rike ->
            mkN rike (rike + "t") (rike + "n") (rik + "ena") ;

          decl5 : Str -> N = \lik ->
            mkN lik (lik + "et")  lik  (lik + "en") ;

    ### What paradigms are there?

    Swedish nouns traditionally have 5 declensions. But each of them has slight variations. For instance, the "2nd declension" has the following:

          gosse  - gossar  -- 211
          nyckel - nycklar -- 231
          seger  - segrar  -- 232
          öken   - öknar   -- 233
          hummer - humrar  -- 238
          kam    - kammar  -- 241
          mun    - munnar  -- 243

    and many more (S. Hellberg, The Morphology of Present-Day Swedish, Almqvist & Wiksell, Stockholm, 1978). In addition, we have at least

          mås - mås -- genitive form without s
          sax - sax

    ### High-level access to paradigms

    The "naīve user" does not want to go through 500 noun paradigms and pick the right one.

    A much more efficient method is the one used in dictionaries: give two (or more) forms instead of one. Our "dictionary heuristic function" covers the following cases:

          flicka - flickor
          kor    - kor     (koret)
          ko     - kor     (kon)
          ros    - rosor   (rosen)
          bil    - bilar
          nyckel - nycklar
          hummer - humrar
          rike   - riken
          lik    - lik     (liket)
          lärare - lärare  (läraren)

    ### The definition of the dictionary heuristic

        reg2Noun : Str -> Str -> Subst = \bil,bilar ->
           let
             l  = last bil ;
             b  = Predef.tk 2 bil ;
             ar = Predef.dp 2 bilar
           in
           case ar of {
              "or" => case l of {
                 "a" => decl1Noun bil ;
                 "r" => sLik bil ;
                 "o" => mkNoun bil (bil + "n")  bilar (bilar + "na") ;
                 _   => mkNoun bil (bil + "en") bilar (bilar + "na")
                 } ;
              "ar" => ifTok Subst (Predef.tk 2 bilar) bil
                         (decl2Noun bil)
                         (case l of {
                            "e" => decl2Noun bil ;
                            _   => mkNoun bil (bil + "n") bilar (bilar + "na")
                            }
                         ) ;
              "er" => decl3Noun bil ;
              "en" => ifTok Subst bil bilar (sLik bil) (sRike bil) ; -- ben-ben
              _ => ifTok Subst bil bilar (
                     case Predef.dp 3 bil of {
                        "are" => sKikare (init bil) ;
                        _ => decl5Noun bil
                        }
                     )
                     (decl5Noun bil) --- rest case with lots of garbage
              } ;

    ### When in doubt...

    Test in GF by generating the table

          > cc mk2N "öken" "öknar"
          {s = table Number {
            Sg => table {
              Indef => table Case {
                Nom => "öken" ;
                Gen => "ökens"
              } ;
              Def => table Case {
                Nom => "ökenn" ;
                Gen => "ökenns"
              }
            ...
          }

    Use the worst-case function if the heuristic does not work:

          mkN "öken" "öknen" "öknar" "öknarna"

    ### The module `ParadigmsSwe`

    For each main category - `N`, `A`, `V` - a worst-case function and a couple of "regular" patterns.

          mkN    : (apa,apan,apor,aporna : Str) -> N ;
          mk2N   : (nyckel,nycklar : Str) -> N ;

          mkV    : (supa,super,sup,söp,supit,supen : Str) -> V ;
          regV   : (tala : Str) -> V ;
          mk2V   : (leka,leker : Str) -> V ;
          irregV : (dricka, drack, druckit  : Str) -> V ;

    Construction functions for subcategorization.

          mkV2   : V -> Preposition -> V2 ;
          dirV2  : V -> V2 ;
          mkV3   : V -> Preposition -> Preposition -> V3 ;

    ### Morphology extraction

    Idea: search for characteristic forms of paradigms in a corpus.

          paradigm decl1
            = ap+"a"
              {ap+"a" & ap+"or" };

    For instance, if you find klocka and klockor, add

          klocka = decl1 "klocka" ;

    to the lexicon.

    The notation for extraction and its implementation are developed by Markus Forsberg and Harald Hammarström.

    ### False positives

    Problem: false positives, e.g. bra - bror.

    Solution: restrict stem with a regular expression

          paradigm decl1 [ap : char* vowel char*]
            = ap+"a"
              {ap+"a" & ap+"or" };

    In general, exclude stems shorter than 3 characters.

    To guarantee quality, it is necessary to check the results manually.

    ### Patterns for what?

    "Irregular patterns" are possible, e.g.

          paradigm vEI [sm:OneOrMore, t:OneOrMore]
            = sm+"i"+t+"a"
              {sm+"i"+t+"a" & (sm+"e"+t | sm+"i"+t+"it")} ;

    For rare patterns, it is more productive to build the corresponding part of lexicon manually.

    ### Current Swedish resource lexicon

    49,749 lemmas (1,000 manual, rest extracted), 605,453 word forms. No subcategorization information.

    Uses the Functional Morphology format, which can be translated to GF, XFST, LEXC, MySQL,...

    FM's "native" analysis engine is based on a trie and includes compound analysis using algorithms from G. Huet's Zen Toolkit. Analysis speed is 12,000 words per minute with compound analysis, 50,000 without (on an Intel M1.5 GHz laptop).

    ## Syntax case study: Swedish determiners

    Problem: describe agreement and inheritance of definiteness when a determiner is added to a common noun, possibly modified by an adjective:

    en bil
    bilen

    en stor bil
    den stora bilen

    denna bil
    denna stora bil

    ### Abstract syntax for noun phrases

    The abstract syntax of a GF grammar defines what grammatical structures there are, without telling how they are defined.

    The relevant fragment consists of 5 categories and 4 functions

          cat
            N ;   -- simple (lexical) common noun, e.g. "bil"
            CN ;  -- possibly complex common noun, e.g. "stor bil"
            Det ; -- determiner,                   e.g. "denna"
            NP ;  -- noun phrase,                  e.g. "bilen"
            AP :  -- adjectival phrase,            e.g. "stor"
          fun
            UseN  : N -> CN ;
            UseA  : A -> AP ;
            DetCN : Det -> CN -> NP ;
            ModAP : AP -> CN -> CN ;

    ### The type of complex common nouns

    Phrase categories are similar to lexical types, but often with some extra information.

    Complex common nouns have the following linearization type

          CN = {
            s : Number => SpeciesP => Case => Str ;
            g : Gender ;
            isComplex : Bool
            } ;

    Here we use a new parameter type,

          SpeciesP   = IndefP | DefP Species ;

    to distinguish between three forms:

          IndefP     => "stor bil"
          DefP Indef => "stora bil"
          DefP Def   => "stora bilen"

    ### Simple and complex common nouns

    The boolean feature `isComplex` is `False` for "one-word" `CN`s. Adjectival modification makes it `True`. Notice also the agreement of the adjective to the noun.

          UseN hus =
            {s = \\n,b,c => hus.s ! n ! unSpeciesP b ! c ;
             g = hus.g ;
             p = False
            } ;

          ModAP Stor Nybil =
            {s = \\n, b, c =>
                   let
                     stor  = Stor.s ! mkAdjForm (unSpeciesAdjP b) n Nybil.g ! Nom ;
                     nybil = Nybil.s ! n ! b ! c
                   in preOrPost God.p nybil god ;
             g = Nybil.g ;
             p = True
             } ;

    ### The type of noun phrases

    A noun phrase must carry the agreement features that are passed to a predicate: number, gender, and person.

          NP = {
            s : NPForm => Str ;
            g : Gender ;
            n : Number ;
            p : Person
            } ;

    Since pronouns have special accusative and possessive forms, the case of noun phrases is richer than the case of nouns.

          NPForm = PNom | PAcc | PGen GenNum ;

          GenNum = ASg Gender | APl ;

    ### The type of determiners

    A determiner agrees to the noun in gender, and determines the number and species of the noun.

          Det = {
            s : Gender => Str ;
            n : Number ;
            b : SpeciesP
            } ;

    Some examples:

          en_Det    = {s = genForms "en"    "ett"   ; n = Sg ; b = IndefP} ;

          denna_Det = {s = genForms "denna" "detta" ; n = Sg ; b = DefP Indef} ;

          den_Det   = {s = genForms "den"   "det"   ; n = Sg ; b = DefP Def} ;

          dessa_Det = {s = \\ _ =>  "dessa"         ; n = Pl ; b = DefP Indef} ;

    ### Building noun phrases with a determiner

    Mutual agreement:
    - the determiner gets the gender of the noun
    - the noun gets the number and definiteness of the determiner

          DetCN : Det -> CN -> NP = \en, man ->
            {s = \\c => en.s ! man.g ++
                        man.s ! en.n ! en.b ! npCase c ;
             g = genNoun man.g ;
             n = en.n ;
             p = P3
            } ;

    ### Definite noun phrases

    Rather than a determiner like the English "the", we use a primitive way of forming definite noun phrases.

          DefNP : CN -> NP ;

    So we can deal with the fact that only complex common nouns get a determiner word.

          DefNP storbil = case storbil.isComplex of {
            True  => DetCN den_det   storbil ;
            False => DetCN empty_Det storbil
            }
             where
               empty_Det = {s = \\_ => [] ; n = Sg ; b = DefP Def} ;

    ## Syntax case study: Swedish sentence structure

    Data: freedom in word order in main clause

           jag har inte sett dig idag
           dig jag har inte sett idag
           idag har jag inte sett dig
           inte har jag sett dig idag
          *sett har jag inte dig idag
           sett dig har jag inte idag

    Rigid order in questions...

          har jag inte sett dig idag

    ... and in subordinate clauses

          jag inte har sett dig idag

    ### The topological model

    P. Diderichsen, for Danish, 1946; here acc. to Jörgensen & Svensson, Nusvensk grammatik (Gleerups, 2001).

    A sentence (`Sats`) consists of different fields

            Nexus Field       Content Field
            -----------       -------------
            V1   N1    A1      V2   N2    A2
            har  jag  inte    sett  dig  idag

    ### Main clause, inverted clause, subordinate clause

    The declarative main clause has an initial fundament, on which (almost) any of the fields (except V1) may occur:

            Fundament  Nexus Field       Content Field
            ---------  -----------       -------------
                       V1   N1    A1      V2   N2    A2
            jag        har  _    inte    sett  dig  idag
            inte       har  jag  _       sett  dig  idag
            dig        har  jag  inte    sett  _    idag
            idag       har  jag  inte    sett  dig  _

    The inverted clause has a rigid order

            V1   N1    A1      V2   N2    A2
            har  jag  inte    sett  dig  idag

    The subordinate clause has another rigid order

            N1   A1    V1      V2   N2    A2
            jag  inte  har    sett  dig  idag

    ### The `Sats` data type

    What would be more natural than to use a record type in GF?

          Sats = {
            s1 : Str ;  -- V1
            s2 : Str ;  -- N1
            s3 : Str ;  -- A1
            s4 : Str ;  -- V2
            s5 : Str ;  -- N2
            s6 : Str    -- A2
            } ;

    A "finished" sentence has three parameters,

          S = {s : Order => Str} ;

          Order = Main | Inv | Sub ;

    ### Building clauses from `Sats`

           SSats sats =
              let
                har  = sats.s1 ;
                jag  = sats.s2 ;
                inte = sats.s3 ;
                sett = sats.s4 ;
                dig  = sats.s5 ;
                idag = sats.s6
              in {s = table {
                Main => variants {
                  jag  ++ har ++ inte ++ sett ++ dig  ++ idag ;
                  inte ++ har ++ jag  ++ sett ++ dig  ++ idag ;
                  dig  ++ har ++ jag  ++ inte ++ sett ++ idag ;
                  idag ++ har ++ jag  ++ inte ++ sett ++ dig
                  } ;
                Inv => har ++ jag  ++ inte ++ sett ++ dig ++ idag ;
                Sub => jag ++ inte ++ har  ++ sett ++ dig ++ idag
                }
              } ;

    ### Some refinements

  - Add tense variation to sentences; compound tenses have more variants than simple ones.

          festat har jag igår
          sova ska jag idag

  - Add boolean features telling which places are occupied; certain combinations can be blocked and enabled then.

           sovit har jag idag
          *sett har jag dig idag
           sett dig har jag idag

  - Add an extraposition field to enable subcategorization patterns as in

           du har sagt mig att han kommer idag
           att han kommer idag har du sagt mig

    ### Construction of `Sats`

    Following the general principle of data abstraction, we treat `Sats` as an abstract data type.

    This means that we don't explicitly write records, but use a handful of functions for writing records:

          mkSats : NounPhrase -> Verb -> Sats = \subj,verb ->
             let
               harsovit = verbSForm verb Act
             in
             {s1 = \\sf => (harsovit sf).fin ;
              s2 = subj.s ! PNom ;
              s3 = negation ;
              s4 = \\sf => (harsovit sf).inf ++ verb.s1 ;
              s5, s6, s7 = [] ;
              e3,e4,e5,e6,e7 = False
              } ;

    ### More constructors of `Sats`

          insertObject : Sats -> Str -> Sats = \sats, obj ->
             {s5 = sats.s5 ++ obj ;
              s1 = sats.s1 ; s2 = sats.s2 ; s3 = sats.s3 ; s4 = sats.s4 ; s6 = sats.s6 ; s7 = sats.s7 ;
              e5 = True ;
              e3 = sats.e3 ; e4 = sats.e4 ; e6 = sats.e6 ; e7 = sats.e7
              } ;

          insertExtrapos : Sats -> Str -> Sats = ...

          mkSatsObject : NounPhrase -> Verb -> Str -> Sats = \subj,verb,obj ->
            insertObject (mkSats subj verb) obj ;

          mkSatsCopula : NounPhrase -> Str -> Sats = \subj,obj ->
            mkSatsObject subj (verbVara ** {s1 = []}) obj ;

    N.B. these would be nicer to define if GF had record field overwriting:

          insertObject : Sats -> Str -> Sats = \sats, obj ->
            sats ** {s5 = sats.s5 ++ obj ; e5 = True} ;

    ### Verb subcategorization patterns formalized

            -- du sover
            SatsV = mkSats ;

            -- du ser mig
            SatsV2 subj verb obj =
              mkSatsObject subj verb (verb.s2 ++ obj.s ! PAcc) ;

            -- du föredrar honom framför mig
            SatsV3 subj verb obj1 obj2 =
              mkSatsObject subj verb (verb.s2 ++ obj1.s ! PAcc ++ verb.s3 ++ obj2.s ! PAcc) ;

            -- du säger att det regnar
            SatsVS subj verb sent =
              insertExtrapos (mkSats subj verb) (optStr infinAtt ++ sent.s ! Sub) ;

            -- du undrar vem som kommer
            SatsVQ subj verb quest =
              insertExtrapos (mkSats subj verb) (quest.s ! IndirQ) ;

    ### Verb subcategorization patterns (continued)

            -- du berättade mig att det hade regnat
            SatsV2S subj verb obj sent =
              insertExtrapos
                (mkSatsObject subj verb (verb.s2 ++ obj.s ! PAcc))
                (optStr infinAtt ++ sent.s ! Sub) ;

            -- du frågar mig om det regnar
            SatsV2Q subj verb obj quest =
              insertExtrapos
                (mkSatsObject subj verb (verb.s2 ++ obj.s ! PAcc))
                (quest.s ! IndirQ) ;

            -- du är trött
            SatsAP subj adj =
              mkSatsCopula subj (adj.s ! predFormAdj subj.g subj.n ! Nom) ;

    ### Coverage of verb patterns in Swedish Academy Grammar

    The comparison by Karin Cavallin has given us guidelines.

    We have tried to add at least those patterns that are meaningful in the language-independent API.

    ### Remaining problems

    Building the fundament when there are many adverbs on the A1 and A2 slots.

          på torget har jag sett dig idag
          idag har jag sett dig på torget
          ? idag på torget har jag sett dig

    Interrogative and relative pronouns

          som jag har sett idag
          Vem har du sett idag?
          När och var har du sett henne?

    The resource grammar has an old treatment without topology: can we make it nicer?

    ## Danish and Norwegian through parametrization

    Swedish, Danish, and Norwegian are "pretty similar". There are differences in
    - vocabulary: `flicka - pige - jente`
    - orthography: `kaka - kage - kake`
    - some parameters, e.g. Norwegian's three genders
    - determiner syntax:

            den stora bilen, denna stora bil
            den store bil,   denne store bil
            den store bilen, denne store bilen

    - special constructions, e.g. Norwegian's `bilen min`
    Things like agreement and word order are quite the same, at least in the resource API fragment.

    Can we abstract away from the differences and build the three grammars together without copy and paste?

    ### Parametrized modules

    The ultimate technique for avoiding copy and paste. Here's a simple linguistic example: case and agreement,

          interface Agreement = {
            param Agr ; Case ;
            oper subject : Case
            }

          incomplete concrete PredAgr of Pred = {
            lincat
              NP = {s : Case => Str ; a : Agr} ;
              VP = {s : Agr => Str} ;
            lin
              PredVP np vp = {s = np.s ! subject ++ vp.s ! np.a} ;
            }

          instance AgreementFin of Agreement = {
            param Agr  = {n : Number ; p : Person} ;
            param Case = Nom | Gen | ... | Instr ; -- 14 values
            oper subject = Nom ;
            }

          concrete PredFin of Pred = PredAgr with (Agreement = AgreementFin) ;

    ### The Scandinavian module structure

    green = instantiation (no work) ; yellow = instance (some work) ; red = specific (full work)

    ### Differences in `Types`

    Scandinavian interface:

          param
            Gender ;
            NounGender ;

    Swedish instance:

            Gender = Utr | Neutr ;
            NounGender = NUtr Sex | Neutr ;

    Danish instance:

            Gender = Utr | Neutr ;
            NounGender : Type = Gender ;

    Norwegian instance:

            Gender = Masc | Fem | Neutr ;
            NounGender : Type = Gender ;

    ### Differences in `Syntax`

    Scandinavian interface (fragment):

          oper
            specDefPhrase : Species ;
            verbVara, verbHava, verbSkola, verbFinnas : V ;
            relPron  : RP ;
            comparÄn, infinAtt, negInte : Str ;

    Swedish instance:

            specDefPhrase = Def ;
            verbVara      = vara_V ; ...
            relPron       = relPronForms "som" "vars" ;
            comparÄn      = "än" ;

    Danish instance:

            specDefPhrase = Indef ;
            verbVara      = være_V ; ...
            relPron       = relPronForms "som" "hvis" ;
            comparÄn      = "end" ;

    Norwegian instance:

            specDefPhrase = Def ;
            verbVara      = være_V ; ...
            relPron       = relPronForms "som" "hvis" ;
            comparÄn      = "enn" ;

    ### Example: definite noun phrases

    Here is the indefinite article, with just one parameter in place:

          DefNP storbil = case storbil.isComplex of {
            True  => DetCN den_det   storbil ;
            False => DetCN empty_Det storbil
            }
             where
               empty_Det = {s = \\_ => [] ; n = Sg ; b = DefP specDefPhrase} ;

    For denna, which is in the lexicon, we just have different entries

          {s = genForms "denna" "detta" ; n = Sg ; b = DefP Indef}         -- Swe
          {s = genForms "denne" "dette" ; n = Sg ; b = DefP specDefPhrase} -- Dan, Nor

    ### Can we generate the lexicon?

    Idea:

          word + paradigm in Swedish ---> word + paradigm in Danish/Norwegian

    The word is transformed by "sound laws", the paradigm by a general correspondance. Example:

          decl1 "jacka"  ---> decl1 "jakke"

    This is computed to

         {s : SubstForm => Str = table {
            SF Sg Indef Nom => "jakke" ;
            SF Sg Indef Gen => "jakkes" ;
            SF Sg Def Nom   => "jakka" ;
            SF Sg Def Gen   => "jakkas" ;
            SF Pl Indef Nom => "jakker" ;
            SF Pl Indef Gen => "jakkers" ;
            SF Pl Def Nom   => "jakkene" ;
            SF Pl Def Gen   => "jakkenes"
          } ;
          g = Fem
         }

    Notice: we do not need to assume translation equivalence.

    ###