9

// Erstellen Sie einen Scanner, der aus dem uns übermittelten Datenstrom liest CSLexer lexer = neuer CSLexer (neuer ANTLRFileStream (f)); tokens.TokenSource = Lexer;Erstellen eines eigenen C# -Compilers mit ANTLR: Kompilierungseinheit

// Create a parser that reads from the scanner 
CSParser parser = new CSParser(tokens); 

// start parsing at the compilationUnit rule 
CSParser.compilation_unit_return x = parser.compilation_unit(); 
object ast = x.Tree; 

Was kann ich mit dem x tun, die von compilation_unit_return Typ ist, die Wurzel zu extrahieren, ihre Klassen, die Methoden usw.? Muss ich den Adapter herausziehen? Wie mache ich das? Beachten Sie, dass die compilation_unit_return als solche in meinem CSParser definiert ist (die automatisch von ANTLR generiert wird):

public class compilation_unit_return : ParserRuleReturnScope 
    { 
     private object tree; 
     override public object Tree 
     { 
      get { return tree; } 
      set { tree = (object) value; } 
     } 
    }; 

Doch der Baum Ich erhalte vom Typ Objekt ist. Ich laufe mit dem Debugger und schien zu sehen, dass es vom Typ BaseTree ist. Aber BaseTree ist eine Schnittstelle! Ich weiß nicht, wie es sich auf BaseTree bezieht und weiß nicht, wie man Details aus diesem Baum herausholt. Ich muss einen Besucher schreiben, der Besuch in seiner Klasse, Methode, Variablen .... Die ParserRuleReturn-Klasse erstreckt sich von RuleReturnScope und hat ein Start-und Stop-Objekt, das ich nicht weiß, was es ist ... Darüber hinaus , gibt es diese TreeVisitor-Klasse, die von ANTLR zur Verfügung gestellt wird, die verwirrend aussieht. Es erfordert, dass ein Adapter als Parameter an seinen Konstruktor übergeben wird (wenn nicht, wird es den Standard-CommonTreeAdaptor verwenden), weshalb ich gefragt habe, wie man den Adapter-E-Mail-Server erhalten soll. Und andere Probleme auch ... Für die API können Sie sich beziehen auf http://www.antlr.org/api/CSharp/annotated.html

Jetzt bin ich hier geschlagen ... Wenn Sie etwas wissen, bitte helfen Sie. Tausend Dank.

Antwort

3

Ich habe noch nie mit ANTLR von C# gearbeitet, aber API nach Ihrem Link, BaseTree ist eindeutig keine Schnittstelle - es ist ein class ist, und es hat öffentliche Eigenschaften: Type Typen des Knotens zu erhalten, Text zu erhalten (Ich nehme an) Quelltext dazu, und Children, um die Kindknoten zu bekommen. Was brauchst du noch?

+0

Es ist eine abstrakte Klasse ... öffentliche abstrakte Klasse BaseTree: ITree – yeeen

+1

Nun ja, und warum würde es dich stoppen? Sie haben den Wurzelknoten des Baumes, von dem Sie wissen, dass er einen Typ hat, der alle Methoden hat, um seine Kinder abzurufen (und so den Baum in jede Tiefe zu führen). –

-2

Wenn ich gehen einen C# Compiler heute zu machen, hier ist was ich würde tun als ein erster Versuch versuchen:

  1. Beginnen Sie mit dem ANTLR C# 3 Ziel (natürlich bin ich hier voreingenommen - ernsthaft können Sie entweder das CSharp2 oder CSharp3 Ziel verwenden).
  2. Get Visual Studio 2010 mit dem .NET Framework 4. Der Schlüssel hier ist .NET 4 und es ist süße neue Ausdrucksbäume.
  3. Erstellen Sie einen grundlegenden kombinierten Parser. Setzen Sie so wenig Logik wie möglich in den Parser. Es sollte wenige (wenn überhaupt) Aktionen haben, und die Ausgabe sollte eine undekorierte AST sein, die mit LL (1) walker gegangen werden kann.
  4. Erstellen Sie eine Baumgrammatik, um den Baum zu durchlaufen und alle deklarierten Typen zu identifizieren. Es sollte auch die member_declaration Unterbäume für die spätere Verwendung behalten.
  5. Erstellen Sie einen Baum Walker, der eine einzige member_declaration läuft und fügt das Mitglied der TypeBuilder. Behalten Sie die Methodenkörper im Auge, aber führen Sie sie noch nicht durch.
  6. Bauen Sie einen Baumwanderer, der den Körper einer Methode führt. Erstelle eine Expression<TDelegate>, die der Methode entspricht, und verwende die CompileToMethod Methode meine eigene API (siehe Pavels und meine Kommentare), um den IL-Code zu generieren.

Wenn Sie die Dinge in dieser Reihenfolge tun, dann, wenn Sie endlich die Ausdrücke parsen (Methodenrümpfe, Feld initializers), können Sie die string parametrisierte Methoden like this one in der Expression Klasse verwenden Arbeit lösen Mitglieder zu speichern.

+0

Leider kann 'CompileToMethod' in diesem Szenario aufgrund seiner inhärenten Einschränkungen nicht wirklich verwendet werden - es gibt keine Möglichkeit, einen Code in eine andere Methode, die Sie generieren, zu kompilieren, und das Ziel' MethodBuilder' muss für eine statische Methode sein nur. Weitere Informationen finden Sie unter https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=473128. –

+0

Schön. Nun, dann würde ich damit anfangen, einen 'Expression'-Compiler zu erstellen, der in diesen Fällen funktioniert und diesen stattdessen verwendet. :) Ich würde den 'Expression'-Compiler als unabhängiges Modul behalten, damit er mit anderen Projekten verwendet werden kann (und vielleicht werde ich es trotzdem zum Spaß machen). –

+0

Vielleicht nur um ein bisschen von meinem qn oben abzuweichen: Ich hv den Quellcode für antirr-3.1.3. N im Runtime-Ordner gibt es 2 Ordner - CSharp n CSharp3. Da du schon CSharp3 erwähnt hast, weißt du warum es 2 Ordner gibt? Allerdings schien die API online für CSharp nur nicht CSharp3, auch die kompilierte DLL zu sein. Will jemand CSharp3 verwenden, muss er dort die Codes selbst kompilieren? Für mich sieht es so aus, als hätte CSharp3 erweiterte Funktionen, aber in meinem Kontext nicht wirklich relevant. – yeeen

6

Sie können wie so am Anfang der Datei des ASTS Baumart in Grammatik Optionen:

tree grammar CSharpTree; 
options { 
    ASTLabelType = CommonTree 
} 

Ich würde eine dritte Grammatik bauen oder es in Ihre bestehenden Parser Grammatik arbeiten, die den Baum verwandelt sich in Klassen, die Sie erstellen. Angenommen, Sie haben eine Regel, die mit dem Plus-Operator übereinstimmt, und es sind 2 Argumente. Sie können eine Regel definieren diesen Baum passende, die eine Klasse erstellt, die Sie geschrieben haben, nennen wir es so PlusExpression:

plusExpr returns [PlusExpression value] 
    : ^(PLUS left=expr right=expr) { $value = new PlusExpression($left.value, $right.value); } 

ausdr eine andere Regel in der Grammatik Anpassungs Ausdrücke sein würde. links und rechts sind nur Aliasnamen für die Baumwerte. Der Teil zwischen den {} 's wird ziemlich wörtlich in C# -Code umgewandelt, mit der Ausnahme, dass die Variablenreferenzen ersetzt werden. Die Eigenschaft .value aus $ left und $ right stammt von der Rückgabe, die in den Regeln angegeben ist, aus denen sie erstellt wurden.

Verwandte Themen