(* ------------------- VERSION 170 vom 30.09.85 -------------------- *) PACKET silbentrennung DEFINES trenn, schreibe trennvektor, ist ausnahme wort, lade ausnahmen, entlade ausnahmen: (* Programm zur Silbentrennung Autor: Klaus-Uwe Koschnick / Rainer Hahn Stand: 1.7.1 (Febr. 1984) 1.7.4 (Mai 1984) (Ausnahme-Woerterbuch, Verbesserungen) *) (*--------------------- Ausnahme Woerterbuch -----------------------*) DATASPACE VAR ds1 :: nilspace; FILE VAR f; LET name table length = 1024, max hash chars = 5; INT VAR anz worte :: 0, hash index; INITFLAG VAR this packet :: FALSE; TEXT VAR dummy, name ohne trennstellen, trennstellen, blanked name; BOUND ROW name table length TEXT VAR name table; PROC init packet: IF NOT initialized (this packet) THEN anz worte := 0 FI END PROC init packet; PROC init name table: forget (ds1); ds1 := nilspace; name table := ds1; INT VAR i; FOR i FROM 1 UPTO name table length REP cout (i); name table [i] := "" END REP; anz worte := 0. END PROC init name table; PROC lade ausnahmen: lade ausnahmen (last param) END PROC lade ausnahmen; PROC lade ausnahmen (TEXT CONST filename): IF exists (filename) THEN lade ELSE errorstop ("Datei nicht vorhanden") FI. lade: init packet; IF anz worte > 0 THEN IF yes ("überschreiben") THEN init nametable ELIF no ("anfügen") THEN LEAVE lade ausnahmen FI ELSE init nametable FI; line (2); f := sequential file (input, file name); WHILE NOT eof (f) REP get (f, dummy); IF subtext (dummy, 1, 2) = "(*" THEN ueberlese kommentar ELSE lade wort (* Vor.: Worte ohne Blanks *) FI END REP. ueberlese kommentar: WHILE NOT eof (f) AND pos (dummy, "*)") = 0 REP get (f, dummy); END REP. lade wort: line ; anz worte INCR 1; put (anz worte); stelle namen ohne trennstellen her; put (name ohne trennstellen); blanked name := " "; name ohne trennstellen CAT " "; blanked name CAT name ohne trennstellen; hash; IF pos (name table [hash index], blanked name) > 0 THEN put ("(bereits geladen)") ELSE insert char (name ohne trennstellen, " ", 1); name ohne trennstellen CAT trennstellen; name table [hash index] CAT name ohne trennstellen; FI. stelle namen ohne trennstellen her: INT VAR number; name ohne trennstellen := dummy; trennstellen := ""; WHILE pos (name ohne trennstellen, "-") > 0 REP number := pos (name ohne trennstellen, "-"); delete char (name ohne trennstellen, number); trennstellen CAT text (number - 1); trennstellen CAT " " END REP. END PROC lade ausnahmen; PROC entlade ausnahmen (TEXT CONST file name): init packet; IF exists (file name) THEN errorstop ("Datei existiert bereits") ELSE unload FI. unload: f := sequential file (output, file name); INT VAR i; FOR i FROM 1 UPTO name table length REP cout (i); IF name table [i] <> "" THEN putline (f, name table [i]) FI END REP. END PROC entlade ausnahmen; BOOL PROC ist ausnahme wort (TEXT CONST word, INT CONST maximum, INT VAR trenn position): init packet; IF anz worte > 0 THEN blanked name fuer hash bilden; hash; IF pos (name table [hash index], blanked name) > 0 THEN trennstelle suchen FI FI; FALSE. blanked name fuer hash bilden: blanked name := " "; IF maximum <= max hash chars THEN eliminiere ggf satzzeichen hinter dem wort; blanked name CAT subtext (word, 1, min (max hash chars, wortlaenge)) ELSE blanked name CAT subtext (word, 1, maximum); FI. eliminiere ggf satzzeichen hinter dem wort: INT VAR wort laenge := length (word); WHILE letztes zeichen ist kein buchstabe REP wort laenge DECR 1; IF wort laenge <= 2 THEN LEAVE ist ausnahme wort WITH FALSE FI END REP. letztes zeichen ist kein buchstabe: TEXT CONST letztes zeichen :: (word SUB wortlaenge); NOT (letztes zeichen >= "A" AND letztes zeichen <= "Z" OR letztes zeichen >= "a" AND letztes zeichen <= "z" OR letztes zeichen >= "Ä" AND letztes zeichen <= "k" OR letztes zeichen = "ß"). trennstelle suchen: index der ersten ziffer suchen; INT VAR neue ziffer := 0; trenn position := 0; ziffern holen. index der ersten ziffer suchen: dummy := name table [hash index]; INT VAR ziffern index := pos (dummy, blanked name); ziffern index := pos (dummy, " ", ziffern index + 1) + 1. ziffern holen: WHILE ist ziffer REP hole neue ziffer; IF gefundene ziffer ist ausserhalb des trennbereichs THEN LEAVE ist ausnahme wort WITH TRUE FI; trenn position := neue ziffer END REP; LEAVE ist ausnahme wort WITH TRUE. ist ziffer: ziffern index < length (dummy) AND ((dummy SUB ziffern index + 1) = " " OR (dummy SUB ziffern index + 2) = " "). hole neue ziffer: INT VAR ende position :: pos (dummy, " ", ziffern index); neue ziffer := int (subtext (dummy, ziffern index, ende position - 1)); ziffern index := ende position + 1. gefundene ziffer ist ausserhalb des trennbereichs: neue ziffer > maximum. END PROC ist ausnahme wort; PROC hash: INT VAR i; hash index := code (blanked name SUB 2); FOR i FROM 3 UPTO min (length (blanked name), max hash chars) REP hash index INCR hash index; hash index INCR code (blanked name SUB i); decrementiere hash index END REP. decrementiere hash index: WHILE hash index > name table length REP hash index DECR 1023 END REP. END PROC hash; (*-------------- eigentlicher Trenn-Algorithmus --------------*) LET zeichenkette n = "-/", regelmaessig = " bl br chl chr dr fl fr gl gr kl kn kr pf ph pl pr sp st schl schm schn schr schw th tr zw ", vokal string = "aeiouyäöü", buchstaben = "abcdefghijklmnopqrstuvwxyzäöüßABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ", grosse buchstaben = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", trennstrich = ""221"", cv a = 97 , cv b = 98 , cv c = 99 , cv d = 100, cv e = 101, cv f = 102, cv g = 103, cv i = 105, cv k = 107, cv l = 108, cv m = 109, cv n = 110, cv o = 111, cv p = 112, cv r = 114, cv s = 115, cv t = 116, cv u = 117, cv w = 119, cv x = 120, cv y = 121, cv ae = 217 , cv oe = 218 , cv ue = 219 , cv sz = 251, weder h noch ch = 0 , buchstabe h = 1 , zeichenfolge ch = 2 ; INT CONST minus one :: - 1; INT VAR i, grenze, absolute grenze, sonderzeichen trennpos, zeichen vor teilwort, teilwort laenge, a pos, e pos, a pos minus 2, a pos minus 1, a pos plus 1, a pos plus 2, e pos minus 1; ROW 50 INT VAR vektor ; TEXT VAR wort, teilwort, kons gr, search, zeichen; BOOL VAR trennstelle gefunden ; PROC trenn (TEXT CONST word, TEXT VAR part1, trennsymbol, INT CONST maximum): IF ist ausnahme wort (word, maximum, position) THEN ausnahme wort behandlung; LEAVE trenn FI; INT VAR laenge :: length (word) ; IF laenge < 4 THEN trennung nicht moeglich ELSE wort := word ; grenze := min (50, maximum) ; absolute grenze := min (laenge, grenze + 5) ; trennung versuchen FI . ausnahme wort behandlung: IF position <= 0 THEN trennung nicht moeglich ELSE part1 := subtext (word, 1, position); IF pos (zeichenkette n, word SUB position + 1) > 0 THEN trennsymbol := " " ELSE trennsymbol := trennstrich FI FI. trennung nicht moeglich : part 1 := ""; trennsymbol := " ". trennung versuchen : erstelle trennvektor ; IF sonderzeichen trennpos > 0 THEN part 1 := subtext (word, 1, sonderzeichen trennpos) ; trennsymbol := " " ELSE bestimme trennposition ; IF position = 0 THEN trennung nicht moeglich ELSE part 1 := subtext (wort, 1, position) ; trennsymbol := trennstrich FI FI . bestimme trennposition : INT VAR position ; FOR position FROM grenze DOWNTO 1 REP IF vektor [position] = 1 THEN LEAVE bestimme trennposition FI END REP ; position := 0 END PROC trenn ; BOOL PROC buchstabe (INT CONST posi) : pos (buchstaben, wort SUB posi) > 0 OR spezialcode. spezialcode: INT CONST z code :: code (wort SUB posi) ; (zcode > 96 AND zcode < 123). END PROC buchstabe ; OP SPERRE (INT CONST element) : INT CONST w element :: zeichen vor teilwort + element ; IF w element > 0 AND w element <= grenze THEN vektor [w element] := minus one FI END OP SPERRE ; OP SETZE (INT CONST element) : INT CONST w element :: zeichen vor teilwort + element; IF w element > 0 AND w element <= grenze AND vektor [w element] <> minus one THEN vektor [w element] := 1 ; trennstelle gefunden := TRUE FI END OP SETZE ; BOOL PROC vorletzter buchstabe oderkeine trennung oder sperre gesetzt (INT CONST akt buchstabenpos): vorletzter buchstabe (akt buchstabenpos) OR NOT trennung oder sperre gesetzt (akt buchstabenpos). END PROC vorletzter buchstabe oderkeine trennung oder sperre gesetzt; BOOL PROC vorletzter buchstabe (INT CONST akt buchstabenpos): akt buchstabenpos = absolute grenze - 1 END PROC vorletzter buchstabe; BOOL PROC trennung oder sperre gesetzt (INT CONST element): INT CONST w element :: zeichen vor teilwort + element; IF w element > 1 AND w element < teilwort laenge THEN vektor [w element] = 1 OR gesperrt ELSE TRUE FI. gesperrt: IF w element >= length (wort) - 1 THEN TRUE ELSE vektor [w element] = minus one FI. END PROC trennung oder sperre gesetzt; PROC sperren und setzen (INT CONST element) : INT CONST w element :: zeichen vor teilwort + element ; vektor [w element - 1] := minus one; vektor [w element] := 1 END PROC sperren und setzen ; TEXT PROC string (INT CONST anf pos, end pos) : subtext (teilwort, maximum, minimum). maximum: IF anf pos > 1 THEN anf pos ELSE 1 FI. minimum: IF teilwort laenge < end pos THEN teilwort laenge ELSE end pos FI. END PROC string ; BOOL PROC silbenanfang vor (INT CONST akt buchstabenpos): zwei silber (akt buchstabenpos - 2) OR drei silber (akt buchstabenpos - 3) END PROC silbenanfang vor; BOOL PROC silbenanfang nach (INT CONST akt buchstabenpos): zwei silber (akt buchstabenpos + 1) OR drei silber (akt buchstabenpos + 1) END PROC silbenanfang nach; BOOL PROC zwei silber (INT CONST akt buchstabenpos): TEXT VAR zweier :: string (akt buchstabenpos, akt buchstabenpos + 1); length (zweier) = 2 AND pos ("ab an ar be er ge in um un zu re", zweier) > 0 END PROC zwei silber; BOOL PROC drei silber (INT CONST akt buchstabenpos): TEXT VAR dreier :: string (akt buchstabenpos, akt buchstabenpos + 2); length (dreier) = 3 AND pos ("auf aus bei ein end ent mit", dreier) > 0 END PROC drei silber; BOOL PROC reg (INT CONST st pos) : INT CONST code one :: code (teilwort SUB st pos) , code two :: code (teilwort SUB st pos + 1) ; pos (regelmaessig, konsonanten) > 0 . konsonanten : search := " " ; IF code one = cv c THEN search CAT string (st pos, st pos + 2) ELIF code one = cv s AND code two = cv c THEN search CAT string (st pos, st pos + 3) ELSE search CAT string (st pos, st pos + 1) FI ; search CAT " " ; search END PROC reg ; INT PROC grenz position (INT CONST start pos, richtung): INT VAR posit :: start pos ; REP posit INCR richtung UNTIL sonderzeichen oder position unzulaessig END REP; posit - richtung. sonderzeichen oder position unzulaessig: posit = 0 AND posit > absolute grenze OR ist kein buchstabe. ist kein buchstabe: pos (buchstaben, wort SUB posit) = 0 AND kein spezialcode. kein spezialcode: INT CONST z code :: code (wort SUB posit) ; (zcode < 97 OR zcode > 121). END PROC grenz position ; PROC schreibe trennvektor (TEXT CONST ttt): line ; put (ttt); INT VAR ii; FOR ii FROM 1 UPTO length (wort) REP put(vektor [ii]) PER END PROC schreibe trennvektor; PROC erstelle trennvektor : INT VAR akt pos, anfang teilwort, ende teilwort, anzahl, zuletzt, tr pos, ind, code 1, code 2, code 3, rechts von a pos, z code, posit; BOOL VAR sonderzeichen modus, aktueller buchstabe ist vokal, vorsilbe oder nachsilbe; sonderzeichen trennpos := 0 ; trennstelle gefunden := FALSE ; initialisiere trennvektor ; akt pos := grenze ; IF buchstabe (akt pos) THEN zuerst teilwort ELSE zuerst sonderzeichenblock FI; WHILE akt pos > 0 REP IF sonderzeichen modus THEN behandle sonderzeichenblock ELSE suche trennstellen in teilwort FI END REP. initialisiere trennvektor : FOR i FROM 1 UPTO grenze REP vektor [i] := 0 END REP . zuerst teilwort: ende teilwort := grenz position (akt pos, 1) ; sonderzeichen modus := FALSE . zuerst sonderzeichenblock: sonderzeichen modus := TRUE . behandle sonderzeichenblock: WHILE sonderzeichen modus REP IF buchstabe (akt pos) THEN sonderzeichen modus := FALSE ELSE zeichen := wort SUB akt pos ; IF pos (zeichenkette n, zeichen) <> 0 THEN sonderzeichen trennpos := akt pos ; LEAVE erstelle trennvektor FI ; akt pos DECR 1 ; IF akt pos = 0 THEN LEAVE erstelle trennvektor FI FI END REP; ende teilwort := akt pos . suche trennstellen in teilwort: bestimme anfang von teilwort ; IF teilwort lang genug THEN teilwort ausbauen und wandeln ; SPERRE 1 ; SPERRE (teilwort laenge - 1) ; vorsilben untersuchen ; nachsilben untersuchen ; vorsilbe oder nachsilbe := trennstelle gefunden ; trennstelle gefunden := FALSE ; weitere trennstellen suchen ; IF vorsilbe oder nachsilbe THEN LEAVE erstelle trennvektor FI FI ; akt pos := anfang teilwort - 1 ; sonderzeichen modus := TRUE . bestimme anfang von teilwort: anfang teilwort := grenz position (ende teilwort, minus one) . teilwort lang genug: teilwort laenge := ende teilwort - anfang teilwort + 1 ; teilwort laenge > 3 . teilwort ausbauen und wandeln: teilwort := subtext (wort, anfang teilwort, ende teilwort); zeichen vor teilwort := anfang teilwort - 1 ; IF pos (grosse buchstaben, teilwort SUB 1) > 0 THEN replace (teilwort, 1, code (code (teilwort SUB 1) + 32)) FI . (* Es ist nicht notwendig, gross geschriebene Umlaute am Wortanfang zu wandeln! *) weitere trennstellen suchen: e pos := teilwort laenge ; aktueller buchstabe ist vokal := letzter buchstabe ist vokal ; WHILE e pos > 1 REP anzahl := 0 ; a pos := e pos ; IF aktueller buchstabe ist vokal THEN behandle vokalgruppe ELSE behandle konsonantengruppe FI ; IF trennstelle gefunden THEN LEAVE erstelle trennvektor FI ; e pos := a pos - 1 ; END REP . letzter buchstabe ist vokal: pos (vokal string,teilwort SUB e pos) > 0 . behandle vokalgruppe: vokalgruppe lokalisieren ; IF a pos > 1 AND e pos < teilwort laenge THEN a pos plus 1 := a pos + 1 ; a pos plus 2 := a pos + 2 ; IF anzahl = 2 THEN vokal 2 ELIF anzahl > 2 THEN vokal 3 ELSE vokal 1 FI FI . vokalgruppe lokalisieren: zuletzt := 0 ; WHILE aktueller buchstabe ist vokal REP zeichen := teilwort SUB a pos ; IF pos (vokal string,zeichen) > 0 THEN z code := code(zeichen) ; IF zuletzt <> cv e OR (z code <> cv a AND z code <> cv o AND z code <> cv u) THEN anzahl INCR 1 FI ; IF a pos > 1 THEN a pos DECR 1 ; zuletzt := z code ELSE aktueller buchstabe ist vokal := FALSE FI ELSE a pos INCR 1 ; aktueller buchstabe ist vokal := FALSE FI END REP . behandle konsonantengruppe: konsonantengruppe lokalisieren ; IF a pos > 1 AND e pos < teilwort laenge THEN a pos minus 2 := a pos - 2 ; a pos minus 1 := a pos - 1 ; a pos plus 1 := a pos + 1 ; a pos plus 2 := a pos + 2 ; e pos minus 1 := e pos - 1 ; SELECT anzahl OF CASE 1 : konsonant 1 CASE 2 : konsonant 2 OTHERWISE : konsonant 3 END SELECT FI . konsonantengruppe lokalisieren: rechts von a pos := weder h noch ch ; REP zeichen := teilwort SUB a pos ; IF pos (vokal string, zeichen) = 0 THEN anzahl INCR 1 ; IF zeichen = "h" THEN rechts von a pos := buchstabe h ELIF zeichen = "c" AND rechts von a pos = buchstabe h THEN anzahl DECR 1 ; rechts von a pos := zeichenfolge ch ELIF zeichen = "s" AND rechts von a pos = zeichenfolge ch THEN anzahl DECR 1 ; rechts von a pos := weder h noch ch ELSE rechts von a pos := weder h noch ch FI ; IF a pos > 1 THEN a pos DECR 1 ELSE aktueller buchstabe ist vokal := TRUE FI ELSE a pos INCR 1 ; aktueller buchstabe ist vokal := TRUE FI UNTIL aktueller buchstabe ist vokal END REP . vorsilben untersuchen: code 2 := code (teilwort SUB 2); code 3 := code (teilwort SUB 3); IF ch vierer silbe THEN sperren und setzen (4) ELSE restliche vorsilben FI. ch vierer silbe: string (2, 4) = "ach" OR string (2, 4) = "och" OR string (2, 4) = "uch". restliche vorsilben: ind := pos ("abdefghimnrstuvwüu", teilwort SUB 1); SELECT ind OF CASE1(*a*): IF drei silber (1) THEN sperren und setzen (3) ELIF code 2 = cv b (*ab*) THEN IF string(3,5) = "end" (*abend*) THEN SPERRE 2; sperren und setzen (5) ELIF string(3,4) = "er" (*aber*) THEN sperren und setzen (4) ELSE sperren und setzen (2) FI ELIF code 2 = cv n AND string(3,5) <> "alo" (*analo*) THEN SETZE 2 FI CASE2(*b*): IF code 2 = cv e (* be *) THEN IF (teilwort SUB 3) = "h" (* be-handeln usw *) OR (teilwort SUB 3) = "a" (* beamter *) THEN sperren und setzen (2) ELIF string (3, 4) = "ob" (* beobachten *) THEN SETZE 2; sperren und setzen (4) FI ELIF string (2, 3) = "au" (* bauer usw *) THEN sperren und setzen (3) FI CASE3(*d*): IF (code 3 = cv s AND (code 2 = cv i OR code 2 = cv e)) OR string (2, 3) = "ar" (* dis, des, dar*) THEN sperren und setzen (3) ELIF string (2, 4) = "enk" (* denk.. *) THEN sperren und setzen (4) ELIF string(2,5) = "urch" (*durch*) THEN SPERRE 3 ; SETZE 5 FI CASE4(*e*): IF code 2 = cv r AND code 3 <> cv n AND code 3 <> cv d AND string (3, 4) <> "ro" (* er, aber nicht: ern, erd, erro *) THEN SETZE 2 ELIF code 2 = cv x (* ex *) THEN SETZE 2 ELIF (code 2 = cv m AND code 3 = cv p AND (teilwort SUB 4) = "f") OR (code 2 = cv n AND code 3 = cv t) (* empf, ent *) THEN sperren und setzen (3) FI CASE5(*f*): CASE6(*g*): IF string (2, 5) = "egen" (* gegen *) THEN sperren und setzen (5) ELIF string (2, 6) = "leich" (* gleich *) THEN IF vorletzter buchstabe (5) THEN SPERRE 6 ELIF vorletzter buchstabe (6) THEN sperren und setzen (4) ELSE sperren und setzen (6) FI ELIF zwei silber (1) THEN SETZE 2 FI CASE7(*h*): IF string (2, 3) = "in" OR string (2, 3) = "er" (* hin, her *) THEN sperren und setzen (3) FI CASE8(*i*): IF code 2 = cv n (* in *) THEN IF string (3, 5) = "ter" (* inter *) THEN sperren und setzen (5) ELIF subtext (teilwort, 1, 5) = "insbe" THEN sperren und setzen (3) ELSE sperren und setzen (2) FI; FI CASE9(*m*): IF string (2, 3) = "ög" AND teilwort laenge > 5 (* mög *) THEN sperren und setzen (3); FI CASE10(*n*): IF string (2, 4) = "ach" AND teilwort laenge >= 7 AND (teilwort SUB 5) <> "t" (* nach, aber nicht: nacht *) THEN SETZE 4 ELIF string (2, 6) = "ieder" (* nieder *) THEN sperren und setzen (6) ELIF string (2, 5) = "icht" (* nicht *) THEN sperren und setzen (5) ELIF string (2, 3) = "eu" (* neu *) THEN sperren und setzen (3); IF dreisilber (4) THEN sperren und setzen (6) FI ELIF string (2, 5) = "iste" THEN sperren und setzen (2) FI CASE11(*r*): IF code 2 = cv e (* re *) THEN IF silbenanfang nach (4) (* Realeinkommen *) THEN sperren und setzen (4) ELSE sperren und setzen (2) FI FI CASE12(*s*): IF string (2, 6) = "elbst" (* selbst *) THEN sperren und setzen (6); SPERRE 4 FI CASE13(*t*): IF string (2, 3) = "at" (* tat *) THEN sperren und setzen (3) ELIF string (2, 5) = "rans" (* trans *) THEN sperren und setzen (5) ELIF string (2, 4) = "heo" (* theo *) THEN sperren und setzen (4) FI CASE14(*u*): IF code 2 = cv m (* um *) THEN SETZE 2 ELIF code 2 = cv n (* un *) THEN IF code 3 = cv i (* uni *) THEN sperren und setzen (3) ELSE sperren und setzen (2); IF string (3, 5) = "ter" (* unter *) THEN sperren und setzen (5) FI FI FI CASE15(*v*): IF string (2, 3) = "or" OR string (2, 3) = "on" OR string (2, 3) = "er" (* vor, von, ver *) THEN sperren und setzen (3) FI CASE16(*w*): IF code 2 = cv e AND code 3 = cv g (* weg *) THEN sperren und setzen (3) ELIF code 2 = cv i (* wi *) THEN IF string(3,5) = "der" (* wider *) THEN sperren und setzen (5) ELIF string(3,6) = "eder" (* weder *) THEN sperren und setzen (6) FI FI CASE17(*ü*): IF string (2, 4) = "ber" (* über *) THEN sperren und setzen (4) FI CASE18(*z*): IF code 2 = cv u (*zu*) THEN sperren und setzen (2); IF drei silber (3) (* zuein *) THEN sperren und setzen (5) FI FI END SELECT. nachsilben untersuchen: IF (teilwort SUB teilwort laenge) = "t" THEN IF (string (teilwort laenge - 3,teilwort laenge) = "heit" AND (teilwort SUB teilwort laenge - 4) <> "c") OR string (teilwort laenge - 3, teilwort laenge -1) = "kei" THEN sperren und setzen (teilwort laenge - 4) FI ELIF string (teilwort laenge - 2, teilwort laenge) = "tag" THEN sperren und setzen (teilwort laenge - 3) ELIF string (teilwort laenge - 3, teilwort laenge) = "tags" THEN sperren und setzen (teilwort laenge - 4) FI. vokal 1: IF string (a pos, a pos plus 2) = "uel" THEN SETZE a pos FI. vokal 2 : ind := pos (vokal string, teilwort SUB a pos); code 2 := code (teilwort SUB a pos plus 1); SELECT ind OF CASE1(*a*): IF code 2 = cv a OR code 2 = cv i OR code 2 = cv y (*aa,ai,ay*) THEN ELIF code 2 = cv u THEN silbe au behandlung ELSE SETZE a pos FI CASE2(*e*): IF code 2 = cv u AND (teilwort SUB a pos plus 2) = "e" (*eue*) THEN SETZE a pos plus 1 ELIF code 2 = cv o OR code 2 = cv ae OR code 2 = cv ue OR code 2 = cv oe (*eo, eä, eü, eö *) THEN SETZE a pos FI CASE3(*i*): IF code 2 <> cv e AND code 2 <> cv o (* i, aber nicht: ie, io *) THEN SETZE a pos FI CASE4(*o*): IF code 2 = cv o OR code 2 = cv u (* oo, ou *) THEN ELIF code 2 = cv e (* oe *) THEN SETZE a pos plus 1 ELSE SETZE a pos FI CASE5(*u*): IF (teilwort SUB a pos - 1) = "q" (* qu *) THEN ELIF code 2 = cv e (* ue *) THEN SETZE a pos plus 1 ELSE SETZE a pos FI CASE7(*y*): IF code 2 <> cv u (* yu *) THEN SETZE a pos FI OTHERWISE (*äöü*): SETZE a pos END SELECT. silbe au behandlung: IF (teilwort SUB a pos + 2) = "e" (* aue, wie in dau-ernd *) THEN SETZE a pos plus 1 ELIF a pos > 2 AND trennung oder sperre gesetzt (a pos + 2) AND ((teilwort SUB a pos + 2) = "f" OR (teilwort SUB a pos + 2) = "s") (* aus- oder auf-Mittelsilben *) THEN SETZE (a pos - 1) FI. vokal 3 : IF string (a pos, a pos plus 2) <> "eau" AND string (a pos plus 1, a pos+3) <> "eau" THEN IF e pos - a pos = anzahl - 1 THEN SETZE a pos plus 1 ELSE code 1 := code(teilwort SUB a pos) ; tr pos := a pos plus 1 ; IF (code 1 = cv a OR code 1 = cv o OR code 1 = cv u) AND (teilwort SUB a pos plus 1) = "e" THEN tr pos INCR 1 FI; code 2 := code (teilwort SUB tr pos) ; IF (code 2 = cv a OR code 2 = cv o OR code 2 = cv u) AND (teilwort SUB tr pos + 1) = "e" THEN tr pos INCR 1 FI ; SETZE tr pos FI FI . konsonant 1 : ind := pos ("bcklmnrstß", teilwort SUB a pos); SELECT ind OF CASE1(*b*): IF string (a pos minus 1, a pos plus 2) = "über" THEN SETZE a pos minus 2 ELIF silbenanfang nach (a pos) AND NOT trennung oder sperre gesetzt (a pos minus 1) THEN SETZE a pos ELIF vorletzter buchstabe oderkeine trennung oder sperre gesetzt (a pos) THEN SETZE a pos minus 1 FI; CASE2(* c oder ch *): IF ((teilwort SUB a pos plus 1) = "h" AND (silbenanfang nach (a pos plus 1) OR string (a pos, a pos + 3) = "chen")) OR (teilwort SUB a pos plus 1) <> "h" THEN SETZE a pos minus 1 ELSE SETZE a pos plus 1 FI CASE3(*k*): IF string (a pos minus 2, a pos minus 1) = "ti" (* tik *) AND silbenanfang nach (a pos) THEN SETZE a pos ELSE SETZE a pos minus 1 FI CASE4(*l*): IF string (a pos - 3, a pos plus 1) = "reali" THEN SETZE a pos plus 1 ELIF string (a pos minus 1, a pos plus 1) = "aly" THEN SETZE a pos minus 1 ELIF string (a pos minus 2, a pos minus 1) = "ta" (*..tal..*) OR string (a pos minus 2, a pos minus 1) = "na" (*..nal..*) OR string (a pos minus 2, a pos minus 1) = "ia" (*..ial..*) THEN SETZE a pos ELSE SETZE a pos minus 1 FI CASE5(*m*): IF string (a pos minus 2, a pos minus 1) = "to" (* ..tom..*) THEN SETZE a pos ELSE SETZE a pos minus 1 FI CASE6(*n*): IF string (a pos - 4, a pos minus 1) = "gege" OR string (a pos - 4, a pos minus 1) = "nebe" (*gegen, neben*) THEN SETZE (a pos - 3) ; SETZE a pos ELIF string (a pos minus 1, a pos plus 1) = "ini" THEN ELIF NOT silbenanfang vor (a pos) AND ((teilwort SUB a pos minus 1) = "e" (* en *) OR (teilwort SUB a pos minus 1) = "u") (* un *) AND (silbenanfang nach (a pos) OR string (a pos plus 1, a pos plus 2) = "ob") THEN SETZE a pos ELIF string (a pos minus 2, a pos plus 1) = "eina" THEN SETZE a pos ELSE SETZE a pos minus 1 FI CASE7(*r*): IF string (a pos minus 2, a pos minus 1) = "tu" (*..tur..*) THEN IF string (a pos plus 1, a pos plus 2) = "el" OR (string (a pos plus 1, a pos plus 2) = "en" AND string (a pos minus 1, apos +3) <> "ent") (* turel OR <>turentwick*) THEN SETZE a pos minus 1 ELSE SETZE a pos FI ELIF string (a pos minus 2, a pos minus 1) = "ve" (*..ver..*) OR string (a pos minus 2, a pos minus 1) = "vo" (*..vor..*) THEN SETZE a pos ELIF string (a pos minus 2, a pos minus 1) = "te" (* ter *) THEN IF dreisilber (a pos plus 1) OR string (a pos plus 1, a pos plus 1) = "a" (*tera*) OR string (a pos - 3, a pos minus 2) <> "zt" (*zter*) THEN SETZE a pos ELSE SETZE a pos minus 1 FI ELIF (teilwort SUB a pos minus 1) = "e" (* er*) AND silbenanfang nach (a pos) AND string (a pos plus 1, a pos + 3) <> "ung" (*erung*) AND string (a pos plus 1, a pos plus 2) <> "er" (*erer*) THEN SETZE a pos ELIF vorletzter buchstabe oderkeine trennung oder sperre gesetzt (a pos) THEN SETZE a pos minus 1 FI CASE8(*s*): IF string (a pos minus 2, a pos minus 1) = "de" (* des *) OR string (a pos minus 2, a pos minus 1) = "xi" (* ..xis *) THEN SETZE a pos ELIF string (a pos minus 2, a pos minus 1) = "ni" (* nis *) AND silbenanfang nach (a pos) THEN SETZE a pos ELIF vorletzter buchstabe oderkeine trennung oder sperre gesetzt (a pos) THEN SETZE apos minus 1 FI CASE9(*t*): IF string (a pos plus 1, a pos + 3) = "ion" (* tion *) THEN SETZE a pos minus 1 ELIF string (a pos plus 1, a pos + 3) <> "ier" (* imitieren *) AND (string (a pos minus 2, a pos minus 1) = "mi"(*...mit..*) OR string (a pos minus 2, a pos minus 1) = "va"(*privat..*) OR string (a pos minus 2, a pos minus 1) = "fi"(*profit..*) OR string (a pos - 3, a pos minus 1) = "zei")(*..zeit..*) THEN SETZE a pos ELSE SETZE a pos minus 1 FI CASE10(*ß*): IF string (a pos, a pos plus 2) = "ßen" OR vorletzter buchstabe (a pos) THEN SETZE a pos minus 1 ELSE SETZE a pos FI OTHERWISE: IF vorletzter buchstabe oderkeine trennung oder sperre gesetzt (a pos) THEN SETZE a pos minus 1 FI END SELECT. konsonant 2 : kons gr := string (a pos, e pos); IF a pos > 2 AND trennung oder sperre gesetzt (a pos minus 1) THEN ELIF ausnahme fuer zwei konsonanten THEN SETZE a pos ELIF kons gr = "ts" THEN IF NOT trennung oder sperre gesetzt (a pos) (* für <> Tatsache, tatsächlich *) THEN SETZE e pos FI ELIF kons gr = "tz" THEN IF (teilwort SUB a pos plus 2) = "e" (* ..tze.. *) OR (teilwort SUB a pos plus 2) = "u" (* ..tzu.. *) THEN SETZE a pos ELSE SETZE a pos plus 1 FI ELIF string (a pos, a pos plus 1) = "ch"(* ch zaehlt als 1 Buchstabe *) THEN SETZE a pos plus 1 (* darum keine Abfrage mit kons gr *) ELIF (kons gr = "dt" OR kons gr = "kt") AND silbenanfang nach (e pos) THEN SETZE e pos ELIF kons gr = "ns" AND (string (a pos - 2, a pos - 1) = "io" (* ..ions *) OR (string (a pos minus 1, a pos) ="en" (*..ens..*) AND (teilwort SUB a pos minus 2) <> "t")) (* aber nicht ..tensiv*) THEN SETZE e pos ELIF string (a pos minus 2, a pos plus 1) = "nach" THEN IF (teilwort SUB a pos plus 2) <> "t" THEN SETZE a pos plus 1 FI ELIF string (e pos, e pos + 3) = "lich" THEN IF string (a pos minus 2, a pos) = "mög" THEN SETZE a pos ELIF pos ("hg", teilwort SUB e pos minus 1) > 0 THEN SPERRE e pos minus 1 ELSE SETZE e pos minus 1 FI; ELIF (reg (a pos) AND NOT trennung oder sperre gesetzt (a pos)) OR (kons gr = "sp" AND silbenanfang vor (a pos)) THEN SETZE a pos minus 1 ELIF string (a pos, a pos plus 2) = "sch" THEN SETZE a pos plus 2 ELSE SETZE a pos FI. ausnahme fuer zwei konsonanten: string (a pos minus 2, a pos) = "nis" AND a pos > 1 (*..nis.., aber nicht nisten *) OR string (a pos minus 2, a pos plus 1) = "rafr" (* strafrecht *) OR string (a pos - 4, a pos) = "undes" (* Bundes *) OR string (a pos minus 1, a pos + 3) = "unter" OR silbenanfang vor (e pos). konsonant 3 : code 1 := code (teilwort SUB a pos); code 2 := code (teilwort SUB a pos plus 1); code 3 := code (teilwort SUB a pos plus 2); IF NOT (ausnahme 1 OR ausnahme 2 OR ausnahme 3 OR ausnahme 4) THEN suche regelmaessige konsonantenverbindung FI. ausnahme 1 : ind := pos ("cfgklnprt", code (code 1)); SELECT ind OF CASE1(*c*): IF code 2 = cv k (* ck *) THEN SETZE a pos plus 1 ELIF string (a pos, a pos + 3) = "chts" (* Rechts.., Gesichts.., .. machts..*) THEN SETZE (a pos + 3) ELIF string (a pos plus 1, a pos + 5) = "hstag" (* Reichstag *) OR (string (a pos, a pos plus 2) = "chs" AND (* ..chs.. *) string (a pos plus 2, a pos +3) <> "st") THEN SETZE a pos plus 2 ELSE LEAVE ausnahme 1 WITH FALSE FI; TRUE CASE2(*f*): IF code 2 = cv f (*ff*) THEN IF code 3 = cv s THEN SETZE a pos plus 2 (* ffs *) ELSE SETZE a pos plus 1 FI ELIF string (a pos minus 1, a pos plus 1) = "aft" (*..aft..*) THEN IF (teilwort SUB a pos plus 2) = "s" THEN SETZE a pos plus 2 ELSE SETZE a pos plus 1 FI ELSE LEAVE ausnahme 1 WITH FALSE FI; TRUE CASE3(*g*): IF string (a pos minus 2, a pos minus 1) = "ag" (* ags *) THEN SETZE a pos plus 1 ELSE LEAVE ausnahme 1 WITH FALSE FI; TRUE CASE4(*k*): IF string (a pos, a pos plus 1) = "kt" AND silbenanfang nach (a pos plus 1) THEN SETZE a pos plus 1 ELSE LEAVE ausnahme 1 WITH FALSE FI; TRUE CASE5(*l*): IF code 2 = cv d OR code 2 = cv g OR code 2 = cv k (*ld, lg, lk*) THEN SETZE a pos plus 1 ELIF string (a pos, a pos + 4) = "ltspr" (* Anwaltsprogramm *) THEN SETZE (a pos + 2) ELSE LEAVE ausnahme 1 WITH FALSE FI; TRUE CASE6(*n*): IF string (a pos - 2, a pos) = "ein" THEN SETZE a pos ELIF code 2 = cv d (* nd *) THEN IF code 3 = cv s (* nds, wie in ...stands... *) THEN SETZE a pos plus 2 ELSE SETZE a pos plus 1 FI ELIF code 2 = cv g (* ng *) THEN IF code 3 = cv s (* ..ngs.. *) THEN SETZE a pos plus 2 ELIF code 3 = cv r (* ..ngr.. *) THEN SETZE a pos ELIF code 3 = cv l (* ungleich *) THEN ELSE SETZE a pos plus 1 FI ELIF string (a pos - 3, a pos plus 1) = "trans" OR string (a pos - 3, a pos plus 1) = "tions" (*tionsplan*) THEN SETZE a pos plus 1 ELIF string (a pos plus 1, a pos + 6) = "ftsper" (*ftsperspek*) THEN SETZE (a pos + 3) ELSE LEAVE ausnahme 1 WITH FALSE FI; TRUE CASE7(*p*): IF code 2 = cv p (* pp *) OR (code 2 = cv f AND code 3 = cv t) (* pft *) THEN SETZE a pos plus 1; TRUE ELSE FALSE FI CASE8(*r*): IF string (a pos plus 1, a pos + 4) = "tner" (* rtner *) THEN SETZE a pos plus 1 ELIF trennung oder sperre gesetzt (a pos) THEN ELSE LEAVE ausnahme 1 WITH FALSE FI; TRUE CASE9(*t*): IF string (a pos plus 1, a pos plus 2) = "st" (*tst*) THEN SETZE a pos ELIF string (a pos plus 1, a pos plus 2) = "zt" (* letzt.. *) THEN IF (teilwort SUB a pos + 3) = "e" (*letzte..*) THEN SETZE a pos plus 1 ELSE SETZE a pos plus 2 FI ELIF string (apos - 2, a pos plus 1) = "eits" (* ..heits.., ..keits.., ..beits.. *) OR string (a pos plus 1, a pos plus 1)= "z" (*tz*) THEN SETZE a pos plus 1 ELSE LEAVE ausnahme 1 WITH FALSE FI; TRUE OTHERWISE: FALSE END SELECT. ausnahme 2 : IF e pos - a pos = 2 THEN FALSE ELIF code 2 = cv p AND string (a pos plus 2, a pos + 3) = "ft" (* pft *) THEN SETZE a pos plus 2; TRUE ELSE FALSE FI . ausnahme 3 : IF code 1 = cv s THEN IF code 2 = cv t AND code 3 <> cv r (* st, aber nicht: str *) AND pos (vokal string, teilwort SUB a pos plus 2) = 0 THEN SETZE a pos plus 1 ; TRUE ELSE FALSE FI ELIF code 2 = cv s THEN IF code 3 = cv t AND (teilwort SUB a pos + 3) <> "r" AND pos (vokal string, teilwort SUB (a pos + 3)) = 0 THEN SETZE a pos plus 2; TRUE ELSE FALSE FI ELSE FALSE FI . ausnahme 4 : IF string (e pos, e pos + 3) = "lich" THEN IF pos ("hg", teilwort SUB e pos minus 1) > 0 THEN SPERRE e pos minus 1 ELSE SETZE e pos minus 1 FI; TRUE ELSE FALSE FI . suche regelmaessige konsonantenverbindung : FOR posit FROM a pos UPTO e pos minus 1 REP IF reg (posit) THEN SETZE (posit - 1); LEAVE konsonant 3 FI END REP ; IF (teilwort SUB e pos) <> "h" OR (teilwort SUB e pos minus 1) <> "c" THEN SETZE e pos minus 1 ELIF (teilwort SUB e pos - 2) <> "s" THEN SETZE (e pos - 2) ELSE SETZE (e pos - 3) FI END PROC erstelle trennvektor ; END PACKET silbentrennung;