home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* GENERATE.PAS *)
- (* 5.Programm: Programmgenerator, der zur *)
- (* LL(1)-Grammatik einen Parser generiert. *)
- (* (c) 1991 Andreas Tengicki & DMV-Verlag *)
- (* ------------------------------------------------------ *)
- PROGRAM Generate(Input, Output, Datei1, Datei2);
-
- USES Zketten, Dos;
-
- CONST
- Term = ['a'..'z'];
- nTerm = ['A'..'Z'];
- az = '''';
-
- VAR
- fTab : ARRAY ['A'..'Z'] OF
- RECORD
- First : ARRAY [0..51] OF BOOLEAN;
- Benutzt,
- Fertig,
- Gesperrt : BOOLEAN;
- END;
- Sym,
- ActNt,
- Nt : CHAR;
- Datei1,
- Datei2 : Text;
- KommFlag,
- Flag : BOOLEAN;
- Zeile : STRING;
- Pos : INTEGER;
-
-
- FUNCTION Proj(i : CHAR) : INTEGER;
- BEGIN
- IF i IN nTerm THEN
- Proj := Ord(i) - Ord('A')
- ELSE IF i IN Term THEN
- Proj := 26 + Ord(i) - Ord('a')
- ELSE BEGIN
- WriteLn('Projektionsfehler!');
- Halt;
- END;
- END;
-
- PROCEDURE Regelsatz; FORWARD;
- PROCEDURE Regel; FORWARD;
- PROCEDURE Linke_Seite; FORWARD;
- PROCEDURE Ausdruck; FORWARD;
- PROCEDURE Symbol; FORWARD;
- PROCEDURE NonTerminal; FORWARD;
- PROCEDURE Terminal; FORWARD;
- PROCEDURE Faktor; FORWARD;
- PROCEDURE TabellenAufl; FORWARD;
- PROCEDURE Kopie(f : CHAR); FORWARD;
-
- PROCEDURE Error;
- BEGIN
- WriteLn('Fehler !'); Halt;
- END;
-
- PROCEDURE Lese_Next;
- BEGIN
- GetChr(Sym);
- END;
-
- PROCEDURE Regelsatz;
- VAR
- i, j : CHAR;
- BEGIN
- (* Öffnen der Dateien. *)
- Assign(Datei1, 'GENERATE.OU1');
- Rewrite(Datei1);
- Assign(Datei2, 'GENERATE.OU2');
- Rewrite(Datei2);
- (* Initialisieren ... *)
- FOR i := 'A' TO 'Z' DO BEGIN
- FOR j := 'A' TO 'Z' DO
- fTab[i].First[Proj(j)] := FALSE;
- FOR j := 'a' TO 'z' DO
- fTab[i].First[Proj(j)] := FALSE;
- fTab[i].Benutzt := FALSE;
- fTab[i].Fertig := FALSE;
- fTab[i].Gesperrt := FALSE;
- END;
- (* Parsen ... *)
- Regel;
- WHILE Sym = ';' DO BEGIN
- Lese_Next;
- Regel;
- END;
- (* Schließen der Dateien ... *)
- Close(Datei1);
- Close(Datei2);
- END;
-
- PROCEDURE Regel;
- BEGIN
- (* Parsen ... *)
- Linke_Seite;
- (* Prozedurköpfe erzeugen ... *)
- WriteLn(Datei1, ' PROCEDURE ', ActNt:1, '; FORWARD;');
- WriteLn(Datei2, ' PROCEDURE ', ActNt:1, ';');
- WriteLn(Datei2, ' BEGIN');
- (* Parsen ... *)
- IF Sym = '=' THEN Lese_Next
- ELSE Error;
- Ausdruck;
- (* Prozedurende erzeugen ... *)
- WriteLn(Datei2, ' END;');
- END;
-
- PROCEDURE Linke_Seite;
- BEGIN
- (* linke Seite merken *)
- ActNt := Sym;
- KommFlag := FALSE;
- (* Parsen ... *)
- NonTerminal;
- (* Plausibilitätstest *)
- IF fTab [ActNt].Benutzt THEN BEGIN
- WriteLn('Nonterminal wurde bereits beschrieben !');
- Halt;
- END ELSE
- fTab [ActNt].Benutzt := TRUE;
- KommFlag := TRUE;
- END;
-
- PROCEDURE Ausdruck;
- BEGIN
- (* Parsen ... *)
- Faktor;
- WHILE Sym = '|' DO BEGIN
- Lese_Next;
- Faktor;
- END;
- (* Alternativauswahl beenden *)
- WriteLn(Datei2, 'error;');
- END;
-
- PROCEDURE Symbol;
- BEGIN
- (* Parsen ... *)
- IF Sym IN Term THEN
- Terminal
- ELSE IF Sym IN nTerm THEN
- NonTerminal
- ELSE
- Error;
- END;
-
- PROCEDURE NonTerminal;
- BEGIN
- (* Parsen ... *)
- IF Sym IN nTerm THEN BEGIN
- (* Prozeduraufruf erzeugen ... *)
- IF KommFlag THEN WriteLn(Datei2, Sym:1, ';');
- Lese_Next;
- END ELSE
- Error;
- END;
-
- PROCEDURE Terminal;
- BEGIN
- (* Erzeuge Symboltest ... *)
- WriteLn(Datei2, 'IF Sym = ', az, Sym:1, az, ' THEN Lese_Next');
- WriteLn(Datei2, ' ELSE Error;');
- (* Parsen ... *)
- Lese_Next;
- END;
-
- PROCEDURE Faktor;
- VAR
- i : CHAR;
- BEGIN
- (* alternative Auswahlbedingung erzeugen ... *)
- fTab [ActNt].First[Proj(Sym)] := TRUE;
- Write(Datei2, 'IF Sym IN [');
- IF Sym IN Term THEN
- Write(Datei2, az, Sym:1, az)
- ELSE BEGIN (* First ist Nonterminal *)
- FOR i := 'a' TO 'z' DO
- IF fTab [Sym].First[Proj(i)] THEN
- fTab [ActNt].First[Proj(i)] := TRUE;
- FOR i := 'A' TO 'Z' DO
- IF fTab [Sym].First[Proj(i)] THEN
- fTab [ActNt].First[Proj(i)] := TRUE;
- Write(Datei2, '/* ', Sym:1, ' */');
- END;
- WriteLn(Datei2, '] THEN BEGIN');
- (* Parsen ... *)
- Symbol;
- WHILE (Sym IN nTerm) OR (Sym IN Term) DO Symbol;
- (* Alternativauswahl beenden *)
- Write(Datei2, 'END ELSE ');
- END;
-
- PROCEDURE TabellenAufl;
- VAR
- fir : CHAR;
- BEGIN
- FOR Nt := 'A' TO 'Z' DO
- IF fTab [Nt].Benutzt AND NOT fTab [Nt].Fertig THEN BEGIN
- fTab [Nt].Gesperrt := TRUE;
- FOR fir := 'A' TO 'Z' DO
- IF fTab [Nt].First[Proj(fir)] AND
- NOT fTab [fir].Gesperrt THEN Kopie(fir);
- fTab [Nt].Gesperrt := FALSE;
- fTab [Nt].Fertig := TRUE;
- END;
- END;
-
- PROCEDURE Kopie(f : CHAR);
- VAR
- i : CHAR;
- BEGIN
- FOR i := 'a' TO 'z' DO
- IF fTab [f].First[Proj(i)] THEN
- fTab [Nt].First[Proj(i)] := TRUE;
- IF NOT fTab[i].Fertig THEN BEGIN
- fTab [f].Gesperrt := TRUE;
- FOR i := 'A' TO 'Z' DO
- IF fTab [f].First[Proj(i)] AND
- NOT fTab [i].Gesperrt THEN Kopie(i);
- fTab [f].Gesperrt := FALSE;
- END;
- END;
-
- BEGIN
- WriteLn;
- WriteLn;
- WriteLn('Parserstrategien 5.Programm:');
- WriteLn(' Parsergenerator');
- (* Parsen ... *)
- WriteLn;
- Write(': '); Lese_Next;
- Regelsatz;
- IF Sym <> '!' THEN Error;
- WriteLn('1.Pass erfolgreich !');
-
- (* Erzeugen der vollständigen Alternativauswahl *)
- TabellenAufl;
- Assign(Datei1, 'GENERATE.OU3');
- Reset(Datei2);
- Rewrite(Datei1);
- WHILE NOT EoF(Datei2) DO BEGIN
- ReadLn(Datei2, Zeile);
- Pos := InStr('/*', Zeile);
- IF Pos = 0 THEN
- WriteLn(Datei1, Zeile)
- ELSE BEGIN
- Write(Datei1, TeilStr(Zeile, 1, Pos-1));
- ActNt := Zeile[Pos+2];
- Flag := FALSE;
- FOR Sym := 'a' TO 'z' DO
- IF fTab [ActNt].First[Proj(Sym)] THEN BEGIN
- IF Flag THEN Write(Datei1, ',');
- Flag := TRUE;
- Write(Datei1, az, Sym, az);
- END;
- WriteLn(Datei1, TeilStr(Zeile, Pos+5, LenStr(Zeile)));
- END;
- END;
- Close(Datei1);
- Close(Datei2);
- Exec('del', 'generate.ou2');
- Exec('ren', 'generate.ou3 generate.ou2');
- WriteLn('2.Pass erfolgreich !');
-
- END.
- (* ------------------------------------------------------ *)
- (* Ende von GENERATE.PAS *)
-