Er gaat iets mis — vier valkuilen
Leerdoel: je herkent de vier klassieke valkuilen bij het schrijven van een context-vrije grammatica.
De voorbeelden gebruiken weer het mini-grammaticaatje, zodat ze niets van de opdracht weggeven:
Zin -> Groet Naam
Groet -> "hallo" | "hoi"
Naam -> "sam" | "kim"
Een regel zonder pijl
Symptoom: geen FOUT (0x), maar een rode Python-foutmelding die eindigt
op ValueError: not enough values to unpack (expected 2, got 1), en
de motor komt aan geen enkele zin toe.
Oorzaak: een regel in GRAMMATICA zonder ->. Een typfout zoals
=>, een los woord op een eigen regel, of een zin uit de les die per
ongeluk mee is gekopieerd. Een kopje met # ervoor is het niet: alles
achter een # slaat de motor over, net als in Python. Twee pijlen op
één regel geven de spiegelbeeldige melding, too many values to unpack (expected 2).
De motor splitst elke regel op -> en verwacht links een kop en rechts
de onderdelen; staat er geen pijl, dan valt hij daar om, nog voordat hij
naar een zin kijkt.
# FOUT
Naam => "sam"
# De motor zoekt de pijl -> en vindt hem niet: ValueError.
Oplossing:
# GOED
Naam -> "sam"
Vuistregel: elke regel in GRAMMATICA die niet leeg is, heeft precies
één ->. Kijk bij deze melding dus niet naar je zinnen, maar naar de
regel die je het laatst hebt getypt of geplakt.
Aanhalingstekens vergeten bij een terminal
Symptoom: bovenaan de uitvoer staat LET OP: "sam" in de regel "Naam -> sam" heeft nergens een regel, en de zin blijft op FOUT (0x) of
Kon de zin niet ontleden.
Oorzaak: een echt woord (een terminal) hoort tussen aanhalingstekens.
Laat je ze weg, dan denkt de motor dat sam een groep is, en die groep
heeft geen regels, dus hij matcht nooit een woord. Dezelfde melding
krijg je bij conj waar het lexicon Conj heet: hoofdletters tellen
mee, en de motor zegt er dan bij welke naam hij wél kent.
# FOUT
Naam -> sam
# De motor zoekt nu naar een non-terminal 'sam' die nergens
# gedefinieerd is. 'hallo sam' parseert niet.
Oplossing:
# GOED
Naam -> "sam"
Vuistregel: echte woorden krijgen aanhalingstekens, groepen niet. Dat
geldt voor de namen die jij verzint en voor woordsoorten als N, V
en Det.
Een regel vergeten
Symptoom: één bepaalde zin blijft FOUT (0x), terwijl de rest op OK staat.
Oorzaak: er is geen regel voor de constructie die in die zin voorkomt. Een grammatica accepteert alleen wat de regels toelaten; is er geen pad van het startsymbool naar de woorden, dan is de zin ongeldig.
# FOUT — wel een Groet, maar geen regel die 'Zin' definieert
Groet -> "hallo" | "hoi"
Naam -> "sam" | "kim"
# 'hallo sam' lukt niet: er is geen Zin -> Groet Naam
Oplossing: voeg de ontbrekende regel toe.
# GOED
Zin -> Groet Naam
Aanpak: kijk welke zin faalt, ontleed hem met de hand in groepen, en zoek de groep waarvoor je nog geen regel hebt.
Woord staat niet in het lexicon (of hoofdletters/leestekens)
Symptoom: Kon de zin niet ontleden, ook al lijkt je grammatica
compleet.
Oorzaak: het woord staat niet in het lexicon. De motor zet alles eerst om naar kleine letters en splitst op spaties. Een woord dat niet precies zo, in kleine letters, in het lexicon staat, herkent hij nooit.
# Lexicon kent 'sam', maar niet 'alex'
# 'hallo alex' -> Kon de zin niet ontleden
Oplossing: voeg het woord toe bij de juiste woordsoort, bv.
Naam -> "alex".
Leestekens horen er niet bij: typ hallo sam, niet hallo sam., want
het woord sam. met punt staat niet in het lexicon.
Door naar cheatsheet →.