ttlogo.jpg Freie TextTransformer Projekte
Start
Text2HTML
Wikipedia
Yacc2TT
Delphi-Parser
Delphi-Präprozessor
Delphi-Prettyprinter
Java-Parser
C-Präprozessor
C-Parser
HTML4
Nützliches
MIME-Parser
Spamfilter
Weitere Beispiele
Freie Komponenten
  Minimal Website   Impressum

DelphiPrettyPrint


Mit dem Projekt DelphiPrettyPrint.ttp kann die Lesbarkeit von Delphi-Quellcode verbessert werden, indem er auf einheitliche Weise so formatiert wird, dass die Programmstruktur hervortritt. Z.B der Code:

procedure TTable .  InitFieldDefs;

begin
if(FHandle<>nil) then InternalInitFieldDefs else begin
    SetDBFlag(dbfFieldList,True);  end; end;

wird zu:

procedure TTable.InitFieldDefs;
begin
  if ( FHandle <> nil ) then
    InternalInitFieldDefs
  else
    begin
      SetDBFlag ( dbfFieldList, True );
    end;
end;

Der Codeformatierer basiert auf dem Delphi-Parser Delphi.ttp und ist zunächst als Demonstration dafür gedacht, wie aus dem Parser erzeugte Parse-Bäume im TextTransformers zur Erzeugung eines erwünschten Ausgabeformats verwendet werden können. Der Formatierer kann aber durchaus auch als eigenständiges Projekt von Nutzen sein.


Ursprünglicher Pascal-Prettyprinter

Das Projekt wurde inspiriert durch den Pascal-Prettyprinter:

http://www.moorecad.com/standardpascal/prettyp.pas

Einige Merkmale dieses Ursprungs sind noch im gegenwärtigen Projekt zu erkennen. Für den Delphi-Prettyprinter reicht aber der token-basierte Ansatz des Pascal-Formatierers nicht aus. Im weit komplexeren Delphi ist es wichtig zu wissen, an welcher Stelle der Grammatik ein jeweiliges Token steht.


Abarbeitung des Parse-Baums

Die mit grundlegenden Aktionen sind die Einrückung und die Rücknahme der Einrückung des Rands. Jedes Mal, wenn der Seitenrand eingerückt wird, wird der vorherige Wert des Rands auf einen Stapel gelegt. Jedes Mal, wenn der Rand zurückgesetzt wird, wird der letzte Wert vom Stapel genommen, um den vorherigen Wert des Seitenrands zu erhalten.

Diese und andere Aktionen werden ausgelöst, wenn der Parse-Baum von der Spitze nach unten bis zum letzten Blatt durchlaufen wird. Die Aktionen sind in der Funktionstabelle "m_ftTree" den Labels der Knoten zugeordnet. Die Einrückungen werden dabei zumeist von Knoten ausgelöst, die Token repräsentieren, während die Zurücknahme der Einrückung meist am Ende bestimmter Produktionen erfolgt.


Aktionen von Token repräsentierenden Knoten

Ebenso wie im Pascal-Prettyprinter gibt es in DelphiPrettyPrint.ttp eine Tabelle, in der einzelnen Token ein Set von Optionen zugeordnet, die bestimmen, was bei der Ausgabe des Tokens geschen soll.

Die Optionen werden in der folgenden Reihenfolge verarbeitet und rufen die folgenden Aktionen auf:

CRSUPPRESS  - wenn nach dem vorherigen Symbol ein Flag für einen folgenden Zeilenumbruch gesetzt worden ist, wird es zurückgesetzt. 
CRBEFORE  - ein Zeilenumbruch wird vor dem aktuellen Symbol eingefügt, wenn noch nicht vorhanden 
BLANKLINEBEFORE  - eine Leerzeile wird vor dem aktuellen Symbol eingefügt, wenn noch nicht vorhanden 
DINDENT  - die Zeilenrandwerte werden vom Stapel genommen und der Rand wird entsrechend zurückgesetzt 
SPACEBEFORESUPPRESS  - wenn nach dem vorherigen Symbol ein Flag für einen folgenden Leerzeichen gesetzt worden ist, wird es zurückgesetzt. 
SPACEBEFORE  - eine Leerzeichen wird vor dem aktuellen Symbol ausgegeben, wenn noch nicht vorhanden. 

[ an dieser Stelle wird das Symbol ausgegeben ]

SPACEAFTERSUPPRESS  - ein auf das Symbol folgendes Leerzeichen wird unterdrückt 
INDENTBYTAB  - der Seitenrand wird ausgehend vom vorherigen Rand um einen Standardbetrag eingerückt 
INDENTTOCLP  - der Seitenrand wird bis zur aktuellen Zeilenposition eingerückt 
CRAFTER  - das Flag für eine auf das Symbol folgendes Leerzeile wird gesetzt. 

Die Optionen werden in der Initialisierungsroutine "InitPrettyPrint" als Attribute von Knoten gesetzt und in der map "m_mPrettyPrint" gespeichert. In der Aktion "Tree_keyword" werden sie als Kontext zu den folgenden Aktionen weitergeleitet.


Aktionen von Produktionen repräsentierenden Knoten

Die Rücknahme einer Einrückung lässt sich meist nicht so leicht am Auftreten eine bestimmten Tokens festmachen, wie beim "compound_statement", das mit "begin" beginnt und mit "end" endet. Deshalb wird die PopIndent-Aktion meist am Ende bestimmter Produktionen ausgelöst. Z.B. ist dem "for_stmt", in der das Token "do" die Einrückung auslöst, die Aktion "Tree_deindent" zugeordnet.

m_ftTree.add("for_stmt", Tree_deindent);

Im generierten C++-Code sieht die Funktion zu aus:

void Csource_moduleParser::Tree_deindent(state_type& xState, 
                                         const node& xnNode, 
                                         str& xsResult, 
                                         node& xnContext)
{
  node n(Tree_Default( xState, xnNode, xsResult, xnContext ));
  PopIndent();
} 

D.h. es wird zunächst die Defaultaktion "Tree_Default" ausgeführt, in der u.a. die dem "do" zugeordnete Aktion ausgelöst wird, und anschließend wird die PopIndent-Aktion ausgeführt, die den Rand zurücksetzt.



Kommentare

Kommentare werden beim Parsen in der map "m_Comments" als kleine Bäume gespeichert und im letzten Baumknoten als Attribut gemerkt. Bei der Abarbeitung des Delphi-Baums werden die Kommentare im wesentlichen unverändert ausgegeben. Dazu gibt es eine gesonderte Funktionstabelle "m_ftCommentTree" zur Behandlung der Kommentar-Knoten. Bei Zeilenkommentaren wird der Zeilenumbruch auf den sie enden nicht mitgespeichert. Um eventuelle Leerzeilen vermieden wird stattdessen wie bei der CRAFTER-Option ein Flag gesetzt, dass den Umbruch vor Ausgabe des nächsten Tokens bewirkt.


Konfiguration

Am Anfang der Startregel "source_module" werden Zeichen und Grad der Einrückung gesetzt und können vom Benutzer leicht geändert werden.

{{
SetIndenter(' ');
m_iIndent = 2;
}}



Letztes Update: 31.12.09
1.1.6 lokale Einstellungen der Kommentar-Produktionen so korrigiert, dass keine Zeichen ignoriert werden
1.1.5
1.0.8 enthält viele der Änderungen von Delphi.ttp 1.1.0



 to the top