Inhalt
Aktueller Ordner:
pascalPARSER.PAS
PROGRAM parser (INPUT,OUTPUT);
USES CRT;
(***************************************************************************)
(* Paul Koop Chart Parser VKG *)
(* *)
(***************************************************************************)
(*-----------------------------------------------------------------------*)
(* Vereinbarungsteil *)
(*-----------------------------------------------------------------------*)
CONST
c0 = 0;
c1 = 1;
c2 = 2;
c3 = 3;
c4 = 4;
c5 = 5;
c11 = 11;
cmax = 80;
cwort = 20;
CText : STRING(.cmax.) = '';
datei = 'LexikonVKG.asc';
blank = ' ';
CopyRight
= 'Demo-Parser Chart-Parser Version 1.0(c)1992 by Paul Koop';
TYPE
TKategorien = ( VKG, BG, VT, AV, B, A, BBD, BA, AE, AA,
KBG, VBG, KBBD, VBBD, KBA, VBA, KAE, VAE,
KAA, VAA, KAV, VAV);
PTKategorienListe = ^TKategorienListe;
TKategorienListe = RECORD
Kategorie :TKategorien;
weiter :PTKategorienListe;
END;
PTKante = ^TKante;
PTKantenListe = ^TKantenListe;
TKantenListe = RECORD
kante:PTKante;
next :PTKantenListe;
END;
TKante = RECORD
Kategorie :TKategorien;
vor,
nach,
zeigt :PTKante;
gefunden :PTKantenListe;
aktiv :BOOLEAN;
nummer :INTEGER;
nachkomme :BOOLEAN;
CASE Wort:BOOLEAN OF
TRUE :
(inhalt:STRING(.cwort.););
FALSE:
(gesucht :PTKategorienListe;);
END;
TWurzel = RECORD
spalte,
zeigt :PTKante;
END;
TEintrag = RECORD
A,I :PTKante;
END;
PTAgenda = ^TAgenda;
TAgenda = RECORD
A,I :PTKante;
next,
back : PTAgenda;
END;
PTLexElem = ^TLexElem;
TLexElem = RECORD
Kategorie: TKategorien;
Terminal : STRING(.cwort.);
naechstes: PTLexElem;
END;
TGrammatik = ARRAY (.c1..c11.)
OF
ARRAY (.c1..c4.)
OF TKategorien;
CONST
Grammatik : TGrammatik =
(
(VKG, BG, VT, AV),
(BG, KBG, VBG, Leer),
(VT, B, A, Leer),
(AV, KAV, VAV, Leer),
(B, BBd, BA, Leer),
(A, AE, AA, Leer),
(BBd, KBBd, VBBd, Leer),
(BA, KBA, VBA, Leer),
(AE, KAE, VAE, Leer),
(AA, KAA, VAA, Leer)
);
nummer :INTEGER = c0;
(*-----------------------------------------------------------------------*)
(* Variablen *)
(*-----------------------------------------------------------------------*)
VAR
Wurzel,
Pziel : TWurzel;
Pneu : PTKante;
Agenda,
PAgenda,
Paar : PTAgenda;
LexWurzel,
LexAktuell,
LexEintrag : PTLexElem;
Lexikon : Text;
(***************************************************************************)
(* FUNKTIONEN *)
(***************************************************************************)
(*-----------------------------------------------------------------------*)
(* KantenZaehler *)
(*-----------------------------------------------------------------------*)
FUNCTION NimmNummer:INTEGER;
BEGIN
Nummer := Nummer + c1;
NimmNummer := Nummer
END;
(***************************************************************************)
(* PROZEDUREN *)
(***************************************************************************)
(*-----------------------------------------------------------------------*)
(* LexikonLesen *)
(*-----------------------------------------------------------------------*)
PROCEDURE LiesDasLexikon (VAR f:Text;
G:TGrammatik;
l:PTLexElem);
VAR
zaehler :INTEGER;
z11 : 1..c11;
z4 : 1.. c4;
ch : CHAR;
st5 : STRING(.c5.);
BEGIN
ASSIGN(f,datei);
LexWurzel := NIL;
RESET(f);
WHILE NOT EOF(f)
DO
BEGIN
NEW(LexEintrag);
IF LexWurzel = NIL
THEN
BEGIN
LexWurzel := LexEintrag;
LexAktuell:= LexWurzel;
LexEintrag^.naechstes := NIL;
END
ELSE
BEGIN
LexAktuell^.naechstes := LexEintrag;
LexEIntrag^.naechstes := NIL;
LexAktuell := LexAktuell^.naechstes;
END;
LexEintrag^.Terminal := '';
st5 := '';
FOR Zaehler := c1 to c5
DO
BEGIN
READ(f,ch);
st5 := st5 + UPCASE(ch)
END;
REPEAT
READ(f,ch);
LexEintrag^.terminal := LexEintrag^.Terminal + UPCASE(ch);
UNTIL EOLN(f);
READLN(f);
IF st5 = 'ART**' THEN LexEintrag^.Kategorie := Art ELSE
IF st5 = 'N****' THEN LexEintrag^.Kategorie := N ELSE
IF st5 = 'PN***' THEN LexEintrag^.Kategorie := PN ELSE
IF st5 = 'ADJ**' THEN LexEintrag^.Kategorie := Adj ELSE
IF st5 = 'V****' THEN LexEintrag^.Kategorie := V ELSE
IF st5 = 'PRAEP' THEN LexEintrag^.Kategorie := Praep
END;
END;
(*-----------------------------------------------------------------------*)
(* SatzLesen *)
(*-----------------------------------------------------------------------*)
PROCEDURE LiesDenSatz;
VAR
satz: STRING(.cmax.);
zaehler: INTEGER;
BEGIN
CLRSCR;
WRITELN(CopyRight);
WRITE('-----> ');
Wurzel.spalte := NIL;
Wurzel.zeigt := NIL;
READLN(satz);
FOR zaehler := c1 to LENGTH(satz)
DO satz(.zaehler.) := UPCASE(satz(.zaehler.));
Satz := Satz + blank;
Writeln('-----> ',satz);
WHILE satz <> ''
DO
BEGIN
NEW(Pneu);
Pneu^.nummer :=NimmNummer;
Pneu^.wort := TRUE;
NEW(Pneu^.gefunden);
Pneu^.gefunden^.kante := Pneu;
pneu^.gefunden^.next := NIL;
Pneu^.gesucht := NIL;
Pneu^.nachkomme :=FALSE;
IF Wurzel.zeigt = NIL
THEN
BEGIN
Wurzel.zeigt := pneu;
Wurzel.spalte:= pneu;
PZiel.spalte := pneu;
PZiel.zeigt := Pneu;
pneu^.vor := NIL;
Pneu^.zeigt := NIL;
Pneu^.nach := NIL;
END
ELSE
BEGIN
Wurzel.zeigt^.zeigt := Pneu;
Pneu^.vor := Wurzel.zeigt;
Pneu^.nach := NIL;
Pneu^.zeigt := NIL;
Wurzel.zeigt := Wurzel.zeigt^.zeigt;
END;
pneu^.aktiv := false;
pneu^.inhalt := COPY(satz,c1,POS(blank,satz)-c1);
LexAktuell := LexWurzel;
WHILE LexAktuell <> NIL
DO
BEGIN
IF LexAktuell^.Terminal = pneu^.inhalt
Then
BEGIN
pneu^.Kategorie := LexAktuell^.Kategorie;
END;
LexAktuell := LexAktuell^.naechstes;
END;
DELETE(satz,c1,POS(blank,satz));
END;
END;
(*-----------------------------------------------------------------------*)
(* Regel3KanteInAgendaEintragen *)
(*-----------------------------------------------------------------------*)
PROCEDURE Regel3KanteInAgendaEintragen (Kante:PTKante);
VAR
Wurzel,
PZiel :TWurzel;
PROCEDURE NeuesAgendaPaarAnlegen;
BEGIN
NEW(paar);
IF Agenda = NIL
THEN
BEGIN
Agenda := Paar;
Pagenda:= Paar;
Paar^.next := NIL;
Paar^.back := NIL;
END
ELSE
BEGIN
PAgenda^.next := Paar;
Paar^.next := NIL;
Paar^.back := Pagenda;
Pagenda := Pagenda^.next;
END;
END;
BEGIN
IF Kante^.aktiv
THEN
BEGIN
Wurzel.zeigt := Kante^.zeigt;
WHILE wurzel.zeigt <> NIL
DO
BEGIN
IF NOT(wurzel.zeigt^.aktiv)
THEN
BEGIN
NeuesAgendaPaarAnlegen;
paar^.A := kante;
paar^.I := wurzel.zeigt;
END;
Wurzel.zeigt := Wurzel.zeigt^.nach
END
END
ELSE
BEGIN
PZiel.zeigt := Kante;
WHILE NOT(PZiel.zeigt^.Wort)
DO PZiel.Zeigt := PZiel.Zeigt^.Vor;
Wurzel.Zeigt := PZiel.Zeigt;
Wurzel.Spalte := PZiel.Zeigt;
PZiel.Spalte := Pziel.zeigt;
WHILE wurzel.spalte <> NIL
DO
BEGIN
WHILE wurzel.zeigt <> NIL
DO
BEGIN
IF wurzel.zeigt^.aktiv
AND (Wurzel.zeigt^.zeigt = PZiel.spalte)
THEN
BEGIN
NeuesAGendaPaarAnlegen;
paar^.I := kante;
paar^.A := wurzel.zeigt;
END;
Wurzel.zeigt := Wurzel.zeigt^.nach
END;
wurzel.spalte := wurzel.spalte^.vor;
wurzel.zeigt := wurzel.spalte;
END
END
END;
(*-----------------------------------------------------------------------*)
(* AgendaAusgabe *)
(*-----------------------------------------------------------------------*)
PROCEDURE NimmAgendaEintrag(VAR PEintrag:PTAgenda);
BEGIN
IF PAgenda = Agenda
THEN
BEGIN
PEintrag := Agenda;
PAgenda := NIL;
Agenda := NIL;
END
ELSE
BEGIN
PAGENDA := PAGENDA^.back;
PEintrag := PAgenda^.next;
PAGENDA^.next := NIL;
END;
END;
(*-----------------------------------------------------------------------*)
(* Regel2EineNeueKanteAnlegen *)
(*-----------------------------------------------------------------------*)
PROCEDURE Regel2EineNeueKanteAnlegen( Kante :PTKante;
Kategorie :TKategorien;
Gram :TGrammatik );
VAR
Wurzel :TWurzel;
PHilfe,
PGesuchteKategorie :PTKategorienListe;
zaehler,
zaehler2 :INTEGER;
BEGIN
Wurzel.zeigt := Kante;
Wurzel.spalte:= Kante;
WHILE Wurzel.zeigt^.nach <> NIL
DO Wurzel.zeigt := Wurzel.zeigt^.nach;
FOR zaehler := c1 To c11
DO
IF (kategorie = Gram(.zaehler,c1.))
AND (kategorie <> Leer)
THEN
BEGIN
Gram(.zaehler,c1.) := Leer;
NEW(pneu);
Wurzel.zeigt^.nach := pneu;
pneu^.nummer := NimmNummer;
pneu^.vor := Wurzel.zeigt;
Pneu^.nach := NIL;
Pneu^.zeigt := wurzel.spalte;
Wurzel.zeigt := Wurzel.zeigt^.nach;
pneu^.aktiv := true;
pneu^.kategorie := kategorie;
Pneu^.Wort := false;
Pneu^.gesucht := NIL;
Pneu^.gefunden := NIL;
Pneu^.nachkomme := FALSE;
FOR zaehler2 := c2 TO c4
DO
BEGIN
IF Gram(.zaehler,zaehler2.) <> Leer
THEN
BEGIN
NEW(PGesuchteKategorie);
PGesuchteKategorie^.weiter:= NIL;
PGesuchteKategorie^.Kategorie := Gram(.zaehler,zaehler2.);
IF Pneu^.gesucht = NIL
THEN
BEGIN
PHilfe := PGesuchteKategorie;
Pneu^.gesucht := PHilfe;
END
ELSE
BEGIN
PHilfe^.weiter := PGesuchteKategorie;
PHilfe := PHilfe^.weiter;
END
END
END;
Regel3KanteInAgendaEintragen (pneu);
Regel2EineNeueKanteAnlegen(Wurzel.spalte,
pneu^.gesucht^.kategorie,gram);
END;
END;
(*-----------------------------------------------------------------------*)
(* Regel1EineKanteErweiternen *)
(*-----------------------------------------------------------------------*)
PROCEDURE Regel1EineKanteErweitern(paar:PTAgenda);
VAR
PneuHilf,Pneugefneu,AHilf :PTKantenListe;
BEGIN
IF paar^.I^.kategorie = paar^.A^.gesucht^.kategorie
THEN
BEGIN
NEW(pneu);
pneu^.nummer := NimmNummer;
pneu^.kategorie := Paar^.A^.kategorie;
(*---------------------------------------------------*)
Pneu^.gefunden := NIL;
AHilf := Paar^.A^.gefunden;
WHILE AHilf <> NIL
DO
BEGIN
NEW(Pneugefneu);
IF Pneu^.gefunden = NIL
THEN
BEGIN
Pneu^.gefunden := Pneugefneu;
PneuHilf := Pneu^.gefunden;
PneuHilf^.next := NIL;
END
ELSE
BEGIN
PneuHilf^.next := Pneugefneu;
PneuHilf := PneuHilf^.next;
PneuHilf^.next := NIL;
END;
Pneugefneu^.kante := AHilf^.kante;
AHilf := AHilf^.next;
END;
NEW(Pneugefneu);
IF Pneu^.gefunden = NIL
THEN
BEGIN
Pneu^.gefunden := Pneugefneu;
Pneugefneu^.next := NIL;
END
ELSE
BEGIN
PneuHilf^.next := Pneugefneu;
PneuHilf := PneuHilf^.next;
PneuHilf^.next := NIL;
END;
Pneugefneu^.kante := Paar^.I;
(*--------------------------------------------*)
Pneu^.wort := FALSE;
IF Paar^.A^.gesucht^.weiter = NIL
THEN Pneu^.gesucht := NIL
ELSE Pneu^.gesucht := Paar^.A^.gesucht^.weiter;
Pneu^.nachkomme := TRUE;
IF pneu^.gesucht = NIL
THEN Pneu^.aktiv := false
ELSE Pneu^.aktiv := true;
WHILE Paar^.A^.nach <> NIL
DO Paar^.A := Paar^.A^.nach;
Paar^.A^.nach := pneu;
pneu^.vor := Paar^.A;
pneu^.zeigt := Paar^.I^.zeigt;
pneu^.nach := NIL;
Regel3KanteInAgendaEintragen (pneu);
IF Pneu^.aktiv
THEN Regel2EineNeueKanteAnlegen(Pneu^.zeigt,
pneu^.gesucht^.kategorie,Grammatik);
END;
END;
(*-----------------------------------------------------------------------*)
(* SatzAnalyse *)
(*-----------------------------------------------------------------------*)
PROCEDURE SatzAnalyse;
BEGIN
WHILE Agenda <> NIL
DO
BEGIN
NimmAgendaEintrag(Paar);
Regel1EineKanteErweitern(Paar);
END;
END;
(*-----------------------------------------------------------------------*)
(* SatzAusgabe *)
(*-----------------------------------------------------------------------*)
PROCEDURE GibAlleSatzalternativenAus;
CONST
BlankAnz:INTEGER = c2;
VAR
PHilf :PTkantenListe;
PROCEDURE SatzAusgabe(Kante:PTKante;BlankAnz:INTEGER);
VAR
Zaehler:INTEGER;
PHilf :PTKantenListe;
BEGIN
FOR Zaehler := c1 TO BlankAnz DO WRITE(blank);
IF Kante^.kategorie = S THEN WRITELN ('S ') ELSE
IF Kante^.kategorie = NP THEN WRITELN ('NP ') ELSE
IF Kante^.kategorie = VP THEN WRITELN ('VP ') ELSE
IF Kante^.kategorie = Art THEN WRITE ('Art ') ELSE
IF Kante^.kategorie = ATR THEN WRITELN ('ATR ') ELSE
IF Kante^.kategorie = N THEN WRITE ('N ') ELSE
IF Kante^.kategorie = PN THEN WRITE ('PN ') ELSE
IF Kante^.kategorie = PP THEN WRITELN ('PP ') ELSE
IF Kante^.kategorie = Adj THEN WRITE ('Adj ') ELSE
IF Kante^.kategorie = V THEN WRITE ('V ') ELSE
IF Kante^.kategorie = Praep THEN WRITE ('Praep');
IF Kante^.wort
THEN
WRITELN('----> ',Kante^.inhalt)
ELSE
BEGIN
PHilf := Kante^.gefunden;
WHILE PHilf <> NIL
DO
BEGIN
Satzausgabe(PHilf^.kante,Blankanz+c1);
PHilf := Philf^.next;
END
END
END;
BEGIN
WHILE Wurzel.zeigt^.vor <> NIL
DO Wurzel.zeigt := Wurzel.zeigt^.vor;
WHILE Wurzel.zeigt <> NIL
DO
BEGIN
IF (Wurzel.zeigt^.kategorie = S)
AND ((NOT(Wurzel.zeigt^.aktiv))
AND (wurzel.zeigt^.zeigt = NIL))
THEN
BEGIN
WRITELN('S');
PHilf := Wurzel.zeigt^.gefunden;
WHILE PHilf <> NIL
DO
BEGIN
Satzausgabe(PHilf^.kante,Blankanz+c1);
PHilf := Philf^.next;
END
END;
Wurzel.zeigt := Wurzel.zeigt^.nach;
END;
END;
(*-----------------------------------------------------------------------*)
(* FreigabeDesBenutztenSpeicherplatzes *)
(*-----------------------------------------------------------------------*)
PROCEDURE LoescheDieListe;
PROCEDURE LoescheWort(kante :PTKante);
PROCEDURE LoescheSpalte(kante:PTKante);
VAR
Pgefunden :PTKantenListe;
Pgesucht :PTKategorienListe;
PROCEDURE LoescheGesucht(p:PTKategorienListe);
BEGIN
IF p^.weiter <> NIL
THEN LoescheGesucht(p^.weiter);
IF P <> NIL THEN DISPOSE(P);
END;
PROCEDURE LoescheGefunden(Kante:PTKante;p:PTKantenListe);
BEGIN
IF p^.next <> NIL
THEN LoescheGefunden(Kante,p^.next);
DISPOSE(P);
END;
BEGIN(*LoescheSpalte*)
IF Kante^.nach <> NIL
THEN LoescheSpalte(kante^.nach);
IF (NOT Kante^.nachkomme) AND ((Kante^.gesucht <> NIL)
AND (NOT Kante^.wort))
THEN LoescheGesucht(Kante^.gesucht);
IF Kante^.gefunden <> NIL
THEN LoescheGefunden(Kante,Kante^.gefunden);
DISPOSE(Kante)
END;(*LoescheSpalte*)
BEGIN(*LoescheWort*)
IF Kante^.zeigt <> NIL
THEN LoescheWort(Kante^.zeigt);
LoescheSpalte(Kante);
END;(*LoescheWort*)
BEGIN(*LoescheDieListe*)
WHILE Wurzel.spalte^.vor <> NIL
DO Wurzel.spalte := Wurzel.spalte^.vor;
LoescheWort(Wurzel.spalte);
END;(*LoescheDieListe*)
(***************************************************************************)
(* HAUPTPROGRAMM DES CHART PARSERS *)
(***************************************************************************)
BEGIN
Agenda := NIL;
PAgenda := Agenda;
LiesDasLexikon(Lexikon,Grammatik,LexWurzel);
LiesDenSatz;
WHILE Wurzel.spalte^.vor <> NIL
DO Wurzel.spalte := Wurzel.spalte^.vor;
Regel2EineNeueKanteAnlegen(Wurzel.spalte,S,Grammatik);
SatzAnalyse;
GibAlleSatzalternativenAus;
LoescheDieListe;
(***************************************************************************)
(* ENDE DES HAUPTPROGRAMMS DES CHART PARSERS *)
(***************************************************************************)
END.