home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------------------ *)
- (* PRETTY.PAS *)
- (* Pretty erzeugt aus einem Pascal-Programm, das fehlerfrei *)
- (* uebersetzbar ist, ein neues Programm, das entsprechend der *)
- (* Pascal Block-Struktur durch Einruecken uebersichtlich *)
- (* strukturiert ist. *)
- (* Aufruf: *)
- (* PRETTY [[[inputfilename] outputfilename] Einruecktiefe] *)
- PROGRAM Pretty;
- CONST
- blank = ' ';
- TYPE
- tokentype = (iVAR,iTYPE,iCONST,iFUNCT,iPROC,iBEGIN,iRECORD,
- iREPEAT,iCASE,iUNTIL,iEND,iEXTERN,iFORWARD,notoken);
- string10 = STRING[10];
- iotype = (ein,aus);
- VAR
- icol, level, LevelAlt, indent, NextIndent,
- PUIndent, NextPUIndent, i, bow, len, first,
- LineLength, AnzParam, Code, NIndent :INTEGER;
- itoken : tokentype;
- Input,Output : TEXT;
- cha : CHAR;
- Line : STRING[125];
- letter : SET OF CHAR;
- InString,InComment : BOOLEAN;
- Filename : ARRAY[iotype] OF STRING[30];
- ifile : iotype;
- ParStr : STRING[30];
- token : ARRAY[tokentype] OF STRING[10];
- (* ---------------------------------------------------------------- *)
- (* sucht erstes Zeichen in der Zeile *)
- PROCEDURE FirstNonBlank;
- BEGIN
- WHILE (Line[icol] = ' ') AND (icol < LineLength) DO
- icol := Succ(icol);
- first := icol;
- END;
-
- (* prueft Anfang und Ende von Strings und Kommentaren und setzt *)
- (* dementsprechend die Zustandswerte InComment und InString *)
- PROCEDURE StringComment;
- BEGIN
- IF icol <= LineLength THEN BEGIN
- IF (NOT InComment) AND (Ord(Line[icol]) = 39) THEN
- InString := NOT InString;
- IF NOT InString THEN
- IF (Line[icol] = '(') AND (Line[icol+1] = '*') THEN
- InComment := TRUE
- ELSE IF Line [icol] = '{' THEN
- InComment := TRUE
- ELSE IF Line [icol] = '}' THEN
- InComment := FALSE
- ELSE IF (Line[icol] = '*') AND (Line[icol+1] = ')') THEN
- InComment := FALSE;
- END;
- END;
-
- (* sucht den Anfang des naechsten Wortes *)
- PROCEDURE BeginOfWord;
- BEGIN
- WHILE (NOT(Line[icol] IN letter) OR InString OR InComment)
- AND (icol <= LineLength) DO BEGIN
- StringComment; icol := Succ(icol)
- END;
- bow := icol;
- END;
-
- (* sucht das Ende des aktuellen Wortes und bestimmt dessen Laenge *)
- PROCEDURE LengthOfWord;
- BEGIN
- len := icol;
- WHILE (Line[icol] IN letter) AND (icol <= LineLength) DO
- icol := Succ(icol);
- len := icol - len;
- StringComment;
- END;
-
- (* prueft, ob das gefundene Wort zu den gesuchten Token gehoert. *)
- PROCEDURE CheckToken;
- VAR
- found: BOOLEAN;
- word : string10;
-
- (* wandelt in word kleine in große Buchstaben um *)
- PROCEDURE Upper (word: string10; VAR upstr: string10);
- VAR
- i: INTEGER;
- BEGIN
- FOR i := 1 TO len DO
- IF word[i] > 'Z' THEN word[i] := Chr(Ord(word[i])-32);
- upstr := word;
- END;
-
- BEGIN
- itoken := iVAR; Upper(Copy(Line,bow,len),word);
- REPEAT
- found := (word = token[itoken]); itoken := Succ(itoken);
- UNTIL found OR (itoken = notoken);
- itoken := Pred(itoken);
- IF NOT found THEN itoken := notoken;
- END;
-
- BEGIN (* Pretty *)
- token[iVAR] := 'VAR'; token[iTYPE] := 'TYPE';
- token[iCONST] := 'CONST'; token[iFUNCT] := 'FUNCTION';
- token[iPROC] := 'PROCEDURE'; token[iBEGIN] := 'BEGIN';
- token[iRECORD] := 'RECORD'; token[iREPEAT] := 'REPEAT';
- token[iCASE] := 'CASE'; token[iUNTIL] := 'UNTIL';
- token[iEND] := 'END'; token[iEXTERN] := 'EXTERN';
- token[iFORWARD] := 'FORWARD'; token[notoken] := 'NIL';
- Filename[ein] := 'PRETTY.PAS'; (* Default-Werte *)
- Filename[aus] := 'CON'; NIndent := 2;
- letter := ['A'..'Z'] + ['a'..'z']; (* Menge aller Buchstaben *)
- AnzParam := ParamCount; (* Parameter-Analyse *)
- ifile := ein;
- FOR i := 1 TO AnzParam DO BEGIN
- ParStr := ParamStr(i);
- IF ParStr[1] IN letter THEN BEGIN
- IF ifile > aus THEN BEGIN
- WriteLn('FEHLER: zu viel Parameter'); Halt;
- END;
- Filename[ifile] := ParStr; ifile := Succ(ifile);
- END
- ELSE BEGIN
- Val(ParStr,NIndent,Code);
- IF Code <> 0 THEN BEGIN
- WriteLn('FEHLER: unerlaubter Wert ',ParStr); Halt;
- END;
- END;
- END;
- IF Filename[ein] = Filename[aus] THEN BEGIN
- WriteLn('FEHLERR: Eingabe gleich Ausgabe'); Halt;
- END
- ELSE
- WriteLn('PRETTY ', Filename[ein],' ',Filename[aus],' ',NIndent);
- Assign(Input,Filename[ein]); ReSet(Input);
- Assign(Output,Filename[aus]); ReWrite(Output);
- InString := FALSE; InComment := FALSE; (* Anfangswerte *)
- level := 0; LevelAlt := 0; indent := 0; NextIndent := 0;
- PUIndent := 0; NextPUIndent := 0;
- WHILE NOT Eof(Input) DO BEGIN (* Schleife ueber alle Zeilen *)
- ReadLn (Input,Line); icol := 1; LineLength := Length(Line);
- FirstNonBlank;
- WHILE icol <= LineLength DO BEGIN (* Schleife innerhalb der Zeile *)
- BeginOfWord;
- IF icol <= LineLength THEN BEGIN
- LengthOfWord; CheckToken;
- CASE itoken OF
- iVAR..iCONST: BEGIN NextIndent := NIndent; indent := 0; END;
- iFUNCT,iPROC: BEGIN
- indent := 0; NextIndent := 0;
- PUIndent := PUIndent + NIndent + 1;
- NextPUIndent := PUIndent;
- END;
- iBEGIN: BEGIN
- indent := 0; NextIndent := 0;
- level := level + NIndent;
- END;
- iRECORD..
- iCASE: level := level + NIndent;
- iUNTIL: level := level - NIndent;
- iEND: BEGIN
- level := level - NIndent;
- IF level+indent = 0 THEN
- NextPUIndent := PUIndent - NIndent - 1;
- END;
- iEXTERN..
- iFORWARD: NextPUIndent := PUIndent - NIndent - 1;
- END; (* CASE *)
- END;
- END;
- IF level > LevelAlt THEN (* Ausgabe der formatierten Zeile *)
- WriteLn(Output, Copy(blank,1,LevelAlt+indent+PUIndent),
- Copy(Line,first,1+LineLength-first))
- ELSE
- WriteLn(Output, Copy(blank,1,level+indent+PUIndent),
- Copy(Line,first,1+LineLength-first));
- LevelAlt := level; indent := NextIndent; PUIndent := NextPUIndent;
- END;
- Close(Input); Close(Output);
- END.
-