FSA Tutorial

1.     Starten

Start FSA door het commando

fsa tkconsol=on -tk

Je ziet nu een scherm  met daarin een regel 'Regex' waarin je reguliere expressies kunt invullen, en een regel 'string' waarin je strings kunt invoeren die door de reguliere expressie al dan niet geaccepteerd worden. Het grootste deel van het scherm zal de automaat laten zien die gecompileerd wordt op basis van de reguliere expressie die in 'Regex' is ingevuld. Het onderste deel van het scherm geeft mededelingen van het programma, vooral van belang voor foutmeldingen. Bovendien wordt hier, als je een woord intypt bij 'string', weergegeven of het woord al dan niet door de automaat geaccepteerd wordt.

Er is een manual voor FSA waarin de syntaxis van reguliere expressies wordt beschreven, en de (vele) extra opties die het systeem kent.

Wanneer je FSA niet tot je beschikking hebt, kun je gebruik maken van de on-line demonstratie versie. Bij deze demo-versie hoort ook een alternatieve tutorial.

2. Een paar eenvoudige voorbeelden van reguliere expressies:

  1. [a*,b*]  : definieert de taal die bestaat uit een willekeurig aantal a's, gevolgd door een willekeurig aantal b's. De strings aaabb, aab, aaaaa, bbb worden allemaal herkend door deze expressie, de strings aba, bbaa, acb, cab niet.
  2. [a,b]* definieert de taal die bestaat uit een willekeurig aantal keren de string ab: ab, ababab, maar niet abba, aabb, of bb.
  3. {a, b} : een a of een b.
  4. ? : een willekeurig symbool
  5. ?*: een willekeurige reeks symbolen
  6. ?- q : alle strings van 1 symbool behalve de q
  7. a..z, 'A'..'Z', '0'..'9': de letter a of b of c ...of z, de letter A of B of C.... of Z, het cijfer 0 of 1 of 2.... of 9.
  8. a ^ : optioneel een a.
  9. $ q : alle strings waarin ergens een q voorkomt (gelijk aan [? *, q, ? *])
  10. ~ $ q : alle strings waarin de q niet voorkomt (gelijk aan (? - q )* )
  11. $ q & $ x  : alle strings waarin zowel een q als een x (in willkeurige volgorde) voorkomt.

3. Oefeningen

  1. Geef een reguliere expressie voor `woorden', d.w.z. alle strings die slechts bestaan uit letters
  2. Geef een reguliere expressie voor `cijfer woorden', d.w.z. alle strings die naast letters ook minstens een cijfer bevatten (Windows95,  dvi2ps,  2K, ...).
  3. Geef een reguliere expressie voor `complexe woorden, d.w.z. alle strings die naast letters ook minstens een ander teken (behalve de spatie) bevatten (zwart-wit,  windows3.1)
  4. Geef een reguliere expressie die email adressen (gosse@let.rug.nl) herkent: strings bestaande uit letters, de punt ('.'), en precies 1 apestaart.
  5. Geef een definitie van de `familietaal' uit de syllabus. Kies in het menu 'settings' voor symbol separator 32 (spatie)!

4. Macro's en auxiliary files

Voor de definitie van complexe reguliere expressies kun je gebruik maken van macros. Deze definieer je in een apart (Prolog) bestand, bijvoorbeeld mijn_macros.pl:
macro(klinker,{a,e,i,o,u,y}).
macro(medeklinker, {b,c,d,f,g,hj,k,l,m,n,p,q,r,s,t,v,w,x,z}).
macro(lettergreep, [medeklinker *, klinker +, medeklinker *]).
Je kunt deze macro's laden door in het menu File te kiezen voor LoadAux of Reconsult Aux en dan het betreffende bestand te selecteren.

Daarna kun je in de Regex regel bijvoorbeeld klinker gebruiken. Deze expressie zal worden vertaald als bovenstaande reguliere expressie.

Macro's kunnen andere macro's aanroepen (zie lettergreep).

5. Transducers

Transducers kun je definieren door het symbool ':' of 'x' te gebruiken. A:B (A x B) definieert de transducer die de strings die voldoen aan de reguliere expressie A omzet in strings die voldoen aan B. Je test een transucer met de optie transduce. Als de input geaccepteerd wordt, zal het de output als resultaat geven.

5.1. Voorbeelden

  1. [[a:a]*, b:c, [a:a]*] definieert een transducer die reeksen van de vorm [a*,b,a*] als input accepteert, en een reeks [a*,c,a*] oplevert.
  2. [a *, b:c, a *] definieert dezelfde automaat (reguliere expressies zonder ':' worden omgezet in de `indentity automaat voor die expressie.
  3. [{a:c,b,c}*,c] zet de letter a om in c, mits de reeks verder alleen uit b en c bestaat, en eindigt op c.
  4. {[{a:c,b,c}*,c] ,[{a:b,b,c}*,b]} zet a om in c als de reeks eindigt op c, en zet a om in b als de reeks eindigt op b. Merk op dat dit een non-deterministisch proces is: je kunt pas beslissen of a een c of een b wordt, als je de laatste letter weet.
  5. {klinker:'V',medeklinker:'C'}* vertaalt woorden in CV patronen (op letterniveau), mits klinker en medeklinker als macro gedefinieerd zijn.

5.2. Nieuwe Spelling

Stel dat we systematisch de lettercombinatie qu willen vervangen door kw, en x door ks (aqua wordt akwa, examen wordt eksamen, aanrecht blijft aanrecht, en exquis wordt ekskwis (bah...)

Regels

Een eerste poging voor de x-regel zou kunnen zijn zou kunnen zijn: Dit definieert een transducer die strings waarin x minstens eenmaal voorkomt omzet in dezelfde string, met x vervangen door ks. Merk op dat '? *' hier een willekeurige reeks symbolen is, die steeds op zichzelf worden afgebeeld. We hadden ook kunnen schrijven identity(? *) Dit is niet goed, omdat x soms niet voorkomt (aanrecht) en soms 2 maal voorkomt (xerox, exotoxine). Een verbetering is Deze transducer herkent een willekeurige string, gevolgd door een willekeurig aantal malen (0 of meer) x gevolgd door een willekeurige reeks symbolen. Deze transducer doet nog steeds niet wat we willen, omdat x niet verplicht door ks vervangen wordt. De beginreeks (? *) kan immers x bevatten, en de tweede reeks kan eventueel leeg zijn, zodat exoot op eksoot maar ook op exoot wordt afgebeeld.

Regelcontexten

Hoe definieren we een reeks waarin x niet voorkomt?
  1. macro(geen_x,[? * - x]).
  2. macro(geen_x,[(? - x)*]).
  3. macro(geen_x, ~ $(x)).
Dit kan op twee manieren. Oplossing nummer 1 is FOUT, omdat daar een willekeurige reeks symbolen minus de REEKS x wordt gedefinieerd. Wanneer een reeks dus uit twee of meer symbolen bestaat wordt ze geaccepteerd, ongeacht de vraag of x in de reeks voorkomt. De twee andere oplossingen zijn correct, waarbij in 3 gebruik wordt gemaakt van de substring-operator.

Met de macro geen_x kunnen we de juiste regel definieren:

Compositie

Een vergelijkbare regel kan worden gemaakt voor de qu -> kw regel: Tenslotte moeten beide regels gecombineerd worden. Dit kan door de compositie van beide transducers te nemen. De compositie van twee automaten A en B is de automaat die als input de input van A heeft, vervolgens de output van A als input van B neemt, en als resultaat de output van B geeft. Compositie wordt aangegeven door de operator 'o':

6. Oefeningen

  1. Geef een transducer die ch vervangt door g, en in ander gevallen c vervangt door s of k, overeenkomstig de uitspraak (acht -> agt, cent -> sent, curve -> kurve, etc.)
  2. Geef een transducer die woorden die niet eindigen op -en accepteert, en woorden die wel eindigen op en omzet in woord+en.