Opgave 1 - Definite Clause Grammar

Gegeven is de grammatica uit de syllabus (figuur 2.7 en 2.8), met een paar kleine verschillen. De belangrijkste is dat het woordenboek en de regels gescheiden zijn, zoals uitgelegd in sectie 2.4.

1.1 Uitbreidingen van de grammatica

  • Voeg (minstens) 5 werkwoorden, 5 zelfstandige naamwoorden, en 5 bijvoeglijke naamwoorden toe aan het woordenboek. Test je toevoegingen door een aantal zinnen met de nieuwe woorden te parsen.

    Hint: Voor het (herhaaldelijk) testen van uitbreidingen van de grammatica kun je test-zinnen toevoegen aan het programma:

    sentence(1,[de,flamingo,ontsnapt]).
    
    ungrammatical(1,[beer,de,ontsnapt]).

    Als je nu het predicaat test aanroept wordt voor alle zinnen getest of ze al dan niet worden herkend door de grammatica.

  • Voeg 5 voorzetsels toe aan het woordenboek en een regel voor PP’s. Voeg 5 bijwoorden toe (vandaag, hier, etc.) toe. Je kunt nu het commentaar-teken (%) bij de regels die een pp of een adv introduceren weghalen. Test je toevoegingen weer door zinnen met PPs of bijwoorden te parsen.

  • Voeg meervoudsvormen van de zelfstandige naamwoorden en werkwoorden toe, en pas de grammatica zo aan dat er een verschil tussen enkelvoud en meervoud wordt gemaakt. De zinnen links worden bijvoorbeeld herkend, maar de zinnen rechts niet:

    de beer snurkt          * de beer snurken
    de beren snurken        * de beren snurkt
    de beer wil ontsnappen  * de beer willen ontsnappen
    de bruine beer nadert   * de bruine beer naderen
  • Voeg de woorden ‘een’ en ‘gevaarlijk’ en ‘bruin’ (en andere varianten van adjectieven zonder -e) toe aan het woordenboek. Pas de regels voor NP, A, en N nu zo aan dat je het verschil tussen bijvoeglijke naamwoorden met en zonder ‘e’ beschrijft:

    een bruin beest         * een bruine beest
    het bruine beest        * een bruin beer
    een bruine beer         * het bruin beer
    de bruine beer          * de bruin beer
    de bruine beren         * de bruin beren

N.b. In enkelvoudige NPs hangt de vraag of een adjectief een -e uitgang krijgt af van de vraag of het voorafgaande lidwoord wel of niet ‘een’ is, en de vraag of het erop volgende zelfstandige naamwoord een de- of een het-woord is. Je zult een variabele aan de regels moeten toevoegen om dit verschil te beschrijven. In meervouds NPs krijgt het adjectief altijd de -e uitgang.

1.2 Bomen

Breid de grammatica die je hebt geschreven bij 2.1. uit met een extra argument dat de boom van een zin codeert (zie syllabus, 2.5).

Houd het volgende formaat aan:

b(s,[b(np,[b(det,[w(de)]),
           b(n,[w(hond)])
          ]),
     b(vp,b(v,[w(snurkt)]))
   ])

Voor regels met een ‘lege’ rechterkant kun je het woord epsilon o.i.d. gebruiken.

Het predicaat pprint_tree/1 print deze structuur op een leesbare manier naar het scherm. Wanneer je startsymbool s is, kun je dus het volgende doen:

:- s(Boom,[de,hond,snurkt],[]), pprint_tree(Boom).

om een boom op het scherm te krijgen.

Het predicaat parse/1 roept achtereenvolgens s/3 en pprint_tree/1 aan in een failure-driven loop. (Op die manier kun je snel alle mogelijke boomstructuren voor een zin vinden.) Bijvoorbeeld:

:- parse([de,hond,heeft,gesnurkt]). 

Bedenk tenslotte dat het toevoegen van boomstructuren steeds op dezelfde manier gaat. Slim gebruik van een editor kan helpen.

1.2.a (variant van 1.2. voor de liefhebbers – niet verplicht)

Het is erg omslachtig om steeds aan alle regels een boomstructuur te moeten toevoegen. De toevoeging is bovendien voorspelbaar. Het is daarom handiger om bomen automatisch door prolog te laten toevoegen.

Dit kan door gebruik te maken van ‘term expansion’. Dit is een methode om programma-code tijdens het inlezen om te zetten in andere programmacode. Het predicaat term_expansion/2 zet een term of een clause om in iets anders, gegeven als het tweede argument (zie de SICStus Manual). Zo wordt bv code met de ‘–>’ DCG pijl ook omgezet in gewone prolog regels, met steeds 2 extra argumenten op het eind.

Stel dat je nu je eigen dcg operator definieert, bv ‘==>’. Hiervoor kun je nu ook je eigen term-expansion definieren. Zorg dat je in de definitie van term expansion boompjes (en de extra 2 DCG posities) toevoegt. Vervang nu alle ‘–>’ pijlen in de oude grammatica door ‘==>’ en klaar is kees…..

Een begin van zo’n programma is:

:- op(1100, xfy, ==> ).

:- ensure_loaded(library(lists)).

term_expansion((LHS ==> RHS),(LHS1 :- RHS1)) :-
  LHS =.. [F|Args],
  append(Args, [b(F,Ds),Begin,End], Args1),
  LHS1 =.. [F|Args1],
  expand_daughters(RHS,RHS1,Ds,Begin,End).

De =.. operator zet een term om in een lijst, met als eerste argument de functor en als rest de argumenten (werkt ook andersom). Aan de code ontbreekt alleen nog de definitie van expand_daughters, d.w.z. het recursief door een lijst dochters (gegeven in de vorm (A,(B,….)) heenlopen en steeds vrijwel dezelfde actie uitvoeren als hierboven…

1.3. Ambiguiteit

Geef twee voorbeelden van zinnen in de grammatica zijn de meer dan één boomstructuur opleveren. Beschrijf wat de oorzaak van de ambiguiteit is.

Inleveren

Lever de aangepaste grammatica op, met voorbeelden van zinnen die de uitgebreide grammatica aankan, en je antwoord op vraag 1.3, in, per e-mail naar .

Deze opdracht moet op maandag 4 maart voor 6:00 (in de ochtend) ingeleverd zijn.