home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / dtx9101 / parser / generate.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1991-09-12  |  6.8 KB  |  274 lines

  1. (* ------------------------------------------------------ *)
  2. (*                   GENERATE.PAS                         *)
  3. (*  5.Programm: Programmgenerator, der zur                *)
  4. (*              LL(1)-Grammatik einen Parser generiert.   *)
  5. (*      (c) 1991 Andreas Tengicki & DMV-Verlag            *)
  6. (* ------------------------------------------------------ *)
  7. PROGRAM Generate(Input, Output, Datei1, Datei2);
  8.  
  9. USES Zketten, Dos;
  10.  
  11. CONST
  12.   Term  = ['a'..'z'];
  13.   nTerm = ['A'..'Z'];
  14.   az    = '''';
  15.  
  16. VAR
  17.   fTab  : ARRAY ['A'..'Z'] OF
  18.             RECORD
  19.               First    : ARRAY [0..51] OF BOOLEAN;
  20.               Benutzt,
  21.               Fertig,
  22.               Gesperrt : BOOLEAN;
  23.             END;
  24.   Sym,
  25.   ActNt,
  26.   Nt     : CHAR;
  27.   Datei1,
  28.   Datei2 : Text;
  29.   KommFlag,
  30.   Flag   : BOOLEAN;
  31.   Zeile  : STRING;
  32.   Pos    : INTEGER;
  33.  
  34.  
  35.   FUNCTION Proj(i : CHAR) : INTEGER;
  36.   BEGIN
  37.     IF i IN nTerm THEN
  38.       Proj := Ord(i) - Ord('A')
  39.     ELSE IF i IN Term THEN
  40.       Proj := 26 + Ord(i) - Ord('a')
  41.     ELSE BEGIN
  42.       WriteLn('Projektionsfehler!');
  43.       Halt;
  44.     END;
  45.   END;
  46.  
  47.   PROCEDURE Regelsatz;        FORWARD;
  48.   PROCEDURE Regel;            FORWARD;
  49.   PROCEDURE Linke_Seite;      FORWARD;
  50.   PROCEDURE Ausdruck;         FORWARD;
  51.   PROCEDURE Symbol;           FORWARD;
  52.   PROCEDURE NonTerminal;      FORWARD;
  53.   PROCEDURE Terminal;         FORWARD;
  54.   PROCEDURE Faktor;           FORWARD;
  55.   PROCEDURE TabellenAufl;     FORWARD;
  56.   PROCEDURE Kopie(f : CHAR);  FORWARD;
  57.  
  58.   PROCEDURE Error;
  59.   BEGIN
  60.     WriteLn('Fehler !');  Halt;
  61.   END;
  62.  
  63.   PROCEDURE Lese_Next;
  64.   BEGIN
  65.     GetChr(Sym);
  66.   END;
  67.  
  68.   PROCEDURE Regelsatz;
  69.   VAR
  70.     i, j : CHAR;
  71.   BEGIN
  72.     (* Öffnen der Dateien. *)
  73.     Assign(Datei1, 'GENERATE.OU1');
  74.     Rewrite(Datei1);
  75.     Assign(Datei2, 'GENERATE.OU2');
  76.     Rewrite(Datei2);
  77.       (* Initialisieren ... *)
  78.     FOR i := 'A' TO 'Z' DO BEGIN
  79.       FOR j := 'A' TO 'Z' DO
  80.         fTab[i].First[Proj(j)] := FALSE;
  81.       FOR j := 'a' TO 'z' DO
  82.         fTab[i].First[Proj(j)] := FALSE;
  83.       fTab[i].Benutzt  := FALSE;
  84.       fTab[i].Fertig   := FALSE;
  85.       fTab[i].Gesperrt := FALSE;
  86.     END;
  87.       (* Parsen ... *)
  88.     Regel;
  89.     WHILE Sym = ';' DO BEGIN
  90.       Lese_Next;
  91.       Regel;
  92.     END;
  93.       (* Schließen der Dateien ... *)
  94.     Close(Datei1);
  95.     Close(Datei2);
  96.   END;
  97.  
  98.   PROCEDURE Regel;
  99.   BEGIN
  100.       (* Parsen ... *)
  101.     Linke_Seite;
  102.       (* Prozedurköpfe erzeugen ... *)
  103.     WriteLn(Datei1, '  PROCEDURE ', ActNt:1, ';  FORWARD;');
  104.     WriteLn(Datei2, '  PROCEDURE ', ActNt:1, ';');
  105.     WriteLn(Datei2, '  BEGIN');
  106.       (* Parsen ... *)
  107.     IF Sym = '=' THEN Lese_Next
  108.                  ELSE Error;
  109.     Ausdruck;
  110.       (* Prozedurende erzeugen ... *)
  111.     WriteLn(Datei2, '  END;');
  112.   END;
  113.  
  114.   PROCEDURE Linke_Seite;
  115.   BEGIN
  116.       (* linke Seite merken *)
  117.     ActNt    := Sym;
  118.     KommFlag := FALSE;
  119.       (* Parsen ... *)
  120.     NonTerminal;
  121.       (* Plausibilitätstest *)
  122.     IF fTab [ActNt].Benutzt THEN BEGIN
  123.       WriteLn('Nonterminal wurde bereits beschrieben !');
  124.       Halt;
  125.     END ELSE
  126.       fTab [ActNt].Benutzt := TRUE;
  127.     KommFlag := TRUE;
  128.   END;
  129.  
  130.   PROCEDURE Ausdruck;
  131.   BEGIN
  132.       (* Parsen ... *)
  133.     Faktor;
  134.     WHILE Sym = '|' DO BEGIN
  135.       Lese_Next;
  136.       Faktor;
  137.     END;
  138.       (* Alternativauswahl beenden *)
  139.     WriteLn(Datei2, 'error;');
  140.   END;
  141.  
  142.   PROCEDURE Symbol;
  143.   BEGIN
  144.       (* Parsen ... *)
  145.     IF Sym IN Term THEN
  146.       Terminal
  147.     ELSE IF Sym IN nTerm THEN
  148.       NonTerminal
  149.     ELSE
  150.       Error;
  151.   END;
  152.  
  153.   PROCEDURE NonTerminal;
  154.   BEGIN
  155.       (* Parsen ... *)
  156.     IF Sym IN nTerm THEN BEGIN
  157.         (* Prozeduraufruf erzeugen ... *)
  158.       IF KommFlag THEN WriteLn(Datei2, Sym:1, ';');
  159.       Lese_Next;
  160.     END ELSE
  161.       Error;
  162.   END;
  163.  
  164.   PROCEDURE Terminal;
  165.   BEGIN
  166.       (* Erzeuge Symboltest ... *)
  167.     WriteLn(Datei2, 'IF Sym = ', az, Sym:1, az, ' THEN Lese_Next');
  168.     WriteLn(Datei2, '                             ELSE Error;');
  169.       (* Parsen ... *)
  170.     Lese_Next;
  171.   END;
  172.  
  173.   PROCEDURE Faktor;
  174.   VAR
  175.     i : CHAR;
  176.   BEGIN
  177.       (* alternative Auswahlbedingung erzeugen ... *)
  178.     fTab [ActNt].First[Proj(Sym)] := TRUE;
  179.     Write(Datei2, 'IF Sym IN [');
  180.     IF Sym IN Term THEN
  181.       Write(Datei2, az, Sym:1, az)
  182.     ELSE BEGIN   (* First ist Nonterminal *)
  183.       FOR i := 'a' TO 'z' DO
  184.         IF fTab [Sym].First[Proj(i)] THEN
  185.           fTab [ActNt].First[Proj(i)] := TRUE;
  186.       FOR i := 'A' TO 'Z' DO
  187.         IF fTab [Sym].First[Proj(i)] THEN
  188.           fTab [ActNt].First[Proj(i)] := TRUE;
  189.       Write(Datei2, '/* ', Sym:1, ' */');
  190.     END;
  191.     WriteLn(Datei2, '] THEN BEGIN');
  192.       (* Parsen ... *)
  193.     Symbol;
  194.     WHILE (Sym IN nTerm) OR (Sym IN Term) DO Symbol;
  195.       (* Alternativauswahl beenden *)
  196.     Write(Datei2, 'END ELSE ');
  197.   END;
  198.  
  199.   PROCEDURE TabellenAufl;
  200.   VAR
  201.     fir : CHAR;
  202.   BEGIN
  203.     FOR Nt := 'A' TO 'Z' DO
  204.       IF fTab [Nt].Benutzt AND NOT fTab [Nt].Fertig THEN BEGIN
  205.         fTab [Nt].Gesperrt := TRUE;
  206.         FOR fir := 'A' TO 'Z' DO
  207.           IF fTab [Nt].First[Proj(fir)] AND
  208.              NOT fTab [fir].Gesperrt THEN Kopie(fir);
  209.         fTab [Nt].Gesperrt := FALSE;
  210.         fTab [Nt].Fertig   := TRUE;
  211.       END;
  212.   END;
  213.  
  214.   PROCEDURE Kopie(f : CHAR);
  215.   VAR
  216.     i : CHAR;
  217.   BEGIN
  218.     FOR i := 'a' TO 'z' DO
  219.       IF fTab [f].First[Proj(i)] THEN
  220.         fTab [Nt].First[Proj(i)] := TRUE;
  221.     IF NOT fTab[i].Fertig THEN BEGIN
  222.       fTab [f].Gesperrt := TRUE;
  223.       FOR i := 'A' TO 'Z' DO
  224.         IF fTab [f].First[Proj(i)] AND
  225.            NOT fTab [i].Gesperrt THEN Kopie(i);
  226.       fTab [f].Gesperrt := FALSE;
  227.     END;
  228.   END;
  229.  
  230. BEGIN
  231.   WriteLn;
  232.   WriteLn;
  233.   WriteLn('Parserstrategien 5.Programm:');
  234.   WriteLn('     Parsergenerator');
  235.     (* Parsen ... *)
  236.   WriteLn;
  237.   Write(': '); Lese_Next;
  238.   Regelsatz;
  239.   IF Sym <> '!' THEN Error;
  240.   WriteLn('1.Pass erfolgreich !');
  241.  
  242.     (* Erzeugen der vollständigen Alternativauswahl *)
  243.   TabellenAufl;
  244.   Assign(Datei1, 'GENERATE.OU3');
  245.   Reset(Datei2);
  246.   Rewrite(Datei1);
  247.   WHILE NOT EoF(Datei2) DO BEGIN
  248.     ReadLn(Datei2, Zeile);
  249.     Pos := InStr('/*', Zeile);
  250.     IF Pos = 0 THEN
  251.       WriteLn(Datei1, Zeile)
  252.     ELSE BEGIN
  253.       Write(Datei1, TeilStr(Zeile, 1, Pos-1));
  254.       ActNt := Zeile[Pos+2];
  255.       Flag  := FALSE;
  256.       FOR Sym := 'a' TO 'z' DO
  257.         IF fTab [ActNt].First[Proj(Sym)] THEN BEGIN
  258.           IF Flag THEN Write(Datei1, ',');
  259.           Flag := TRUE;
  260.           Write(Datei1, az, Sym, az);
  261.         END;
  262.       WriteLn(Datei1, TeilStr(Zeile, Pos+5, LenStr(Zeile)));
  263.     END;
  264.   END;
  265.   Close(Datei1);
  266.   Close(Datei2);
  267.   Exec('del', 'generate.ou2');
  268.   Exec('ren', 'generate.ou3 generate.ou2');
  269.   WriteLn('2.Pass erfolgreich !');
  270.  
  271. END.
  272. (* ------------------------------------------------------ *)
  273. (*            Ende von GENERATE.PAS                       *)
  274.