2015-05-04 5 views
10

Ich bin ein Delphi-Code-Parser mit Parsec, meine aktuellen AST Datenstrukturen wie folgt aussehen zu schreiben:Wie kann ich mit Kommentaren in meinem AST umgehen?

module Text.DelphiParser.Ast where 

data TypeName = TypeName String [String] deriving (Show) 
type UnitName = String 
data ArgumentKind = Const | Var | Out | Normal deriving (Show) 
data Argument = Argument ArgumentKind String TypeName deriving (Show) 
data MethodFlag = Overload | Override | Reintroduce | Static | StdCall deriving (Show) 
data ClassMember = 
     ConstField String TypeName 
    | VarField String TypeName 
    | Property String TypeName String (Maybe String) 
    | ConstructorMethod String [Argument] [MethodFlag] 
    | DestructorMethod String [Argument] [MethodFlag] 
    | ProcMethod String [Argument] [MethodFlag] 
    | FunMethod String [Argument] TypeName [MethodFlag] 
    | ClassProcMethod String [Argument] [MethodFlag] 
    | ClassFunMethod String [Argument] TypeName [MethodFlag] 
    deriving (Show) 
data Visibility = Private | Protected | Public | Published deriving (Show) 
data ClassSection = ClassSection Visibility [ClassMember] deriving (Show) 
data Class = Class String [ClassSection] deriving (Show) 
data Type = ClassType Class deriving (Show) 
data Interface = Interface [UnitName] [Type] deriving (Show) 
data Implementation = Implementation [UnitName] deriving (Show) 
data Unit = Unit String Interface Implementation deriving (Show) 

ich Kommentare in meinem AST Datenstrukturen beibehalten werden sollen und ich bin zur Zeit, um herauszufinden, wie zu tun Dies.

Mein Parser ist in einen Lexer und einen Parser aufgeteilt (beide mit Parsec geschrieben) und ich habe bereits das Lexing von Kommentartokens implementiert.

unit SomeUnit; 

interface 

uses 
    OtherUnit1, OtherUnit2; 

type 
    // This is my class that does blabla 
    TMyClass = class 
    var 
    FMyAttribute: Integer; 
    public 
    procedure SomeProcedure; 
    { The constructor takes an argument ... } 
    constructor Create(const Arg1: Integer); 
    end; 

implementation 

end. 

Der Token-Stream sieht wie folgt aus:

[..., Type, LineComment " This is my class that does blabla", Identifier "TMyClass", Equals, Class, ...] 

Der Parser dies schlägt sich in:

Class "TMyClass" ... 

Die Class Datentyp hat keine Möglichkeit, Kommentare zu befestigen und seit Kommentare (vor allem Blockkommentare) könnte fast überall im Token-Stream erscheinen Ich müsste einen optionalen Kommentar zu allen Datentypen in der AST hinzufügen?

Wie kann ich mit Kommentaren in meinem AST umgehen?

+0

Siehe auch http://StackOverflow.com/questions/9392546/pretty-print-haskell-source-code-with-comments und überprüfen Sie, wie diese ASTs definiert sind. Zum Beispiel http://hackage.haskell.org/package/haskell-src-exts-1.16.0.1/docs/Language-Haskell-Extens-Annotated-Syntax.html ist in der Annotation polymorph. – d8d0d65b3f7cf42

Antwort

11

Ein sinnvoller Ansatz für den Umgang mit annotierten Daten in einem AST besteht darin, einen zusätzlichen Typparameter einzufügen, der beliebige Metadaten enthalten kann. Abgesehen davon, dass Sie Kommentare wahlweise hinzufügen oder ignorieren können, können Sie damit auch andere Arten von Informationen in Ihre Struktur aufnehmen.

Zuerst würden Sie alle Ihre AST-Typen mit einem zusätzlichen Parameter umschreiben:

data TypeName a = TypeName a String [String] 
{- ... -} 
data ClassSection a = ClassSection a Visibility [ClassMember a] 
{- ... -} 

Es wäre nützlich, deriving Functor zu allen von ihnen als auch hinzufügen, so dass es leicht, die Anmerkungen zu einem bestimmten AST zu transformieren .

Jetzt hätte ein AST mit den verbleibenden Kommentaren den Typ Class Comment oder etwas in dieser Richtung. Sie können dies auch für zusätzliche Informationen wie die Analyse des Geltungsbereichs verwenden, wobei Sie den aktuellen Geltungsbereich mit dem relevanten Teil des AST einschließen würden.

Wenn Sie mehrere Annotationen auf einmal wünschen, wäre die einfachste Lösung die Verwendung eines Datensatzes, obwohl das ein bisschen peinlich ist, weil wir (zumindest für den Augenblick¹) Code polymorphe Datensätze nicht einfach überschreiben können. (Dh wir können nicht einfach die Art schreiben „jeden Datensatz mit einem comments :: Comment Feld“.)

Eine weitere nette Sache Sie ist PatternSynonyms verwenden tun können (erhältlich von GHC 7.8) eine Reihe von Mustern zu haben, die einfach funktionieren wie Ihre aktuelle unbemerkt AST, so dass Sie Ihre bestehenden Fall Aussagen wiederverwenden können. (Dazu werden Sie auch die Konstrukteure für die kommentierten Typen umbenennen müssen, damit sie sich nicht überlappen.)

pattern TypeName a as <- TypeName' _ a as 

Fußnoten

¹ Hoffentlich Teil 2 der revived overloaded record fields proposal in dieser helfen Beachten Sie, wann es tatsächlich zur Sprache hinzugefügt wird.

Verwandte Themen