2016-04-01 8 views
1

Kann ANTLR verwendet werden, um Quellcode einer Sprache zu analysieren und Quellcode für eine andere Sprache zu erstellen?Verwendung von antlr zum Generieren von Quellcode für eine andere Sprache

Da bisher bei all den Zuhörern ich auf der Suche keinen Weg sehen können separate Einrichtungen zu trennen - wie verschiedene statement Blöcke usw. -, um eine andere Sprache Einrichtungen

(program (programHeading program (identifier HelloWorld) ;) 
(block (procedureAndFunctionDeclarationPart (procedureOrFunctionDeclaration 
(procedureDeclaration procedure (identifier myprocedure) (formalParameterList ( 
(formalParameterSection (parameterGroup (identifierList (identifier x) , (identifier y)) : (typeIdentifier integer))))) ; 
(block (compoundStatement begin (statements (statement (unlabelledStatement (simpleStatement (procedureStatement (identifier writeln) ( 
(parameterList (actualParameter (expression (simpleExpression (term (signedFactor (factor (variable (identifier x))))) + (term (signedFactor 
(factor (unsignedConstant (string ' : '))))) + (term (signedFactor (factor (variable (identifier y)))))))))))))) ; 
(statement (unlabelledStatement (simpleStatement emptyStatement)))) end)))) ;) (compoundStatement begin (statements 
(statement (unlabelledStatement (simpleStatement (procedureStatement (identifier from))))) i := 1 to 10 do begin writeln (i) ;) end)) ; writeln ('Hello, World!') ; end .) 

Zum Beispiel zu schaffen es kann ich nicht Siehe einen Weg zu definieren, wo eine begin Anweisung begann und eine andere endete end.

Nun, ich kann etwas mit stack Helfer tun, aber ich kann Datei Zeile für Zeile selbst in diesem Fall ...

Es ist die Parse-Ergebnis dieser Code

program HelloWorld; 

procedure myprocedure(x, y: integer); 
begin 
    writeln(x + ' : ' + y); 
end; 

begin 
    from i := 1 to 10 do 
    begin 
     writeln(i); 
    end; 
    writeln('Hello, World!'); 
end. 

Vielleicht bin ich einfach analysieren von der falschen Seite schauen oder etwas nicht verstehen?

+0

Versuchen Sie mit Besuchern anstelle von Zuhörern, sie sind besser für diese Art von Dingen geeignet. –

+0

@ LucasTrzesniewski oh ich verstehe. Ich werde es mir ansehen. Ich habe Lexer usw. ohne "visitor" -Flaggen generiert, also habe ich sie nicht bekommen. – lapots

Antwort

2

Ja, ANTLR kann verwendet werden, um eine Sprache L1 in eine Sprache L2 zu übersetzen. Aber das ist nirgends so einfach wie die Menschen es klingen lassen.

Methode1: Erstellen Sie einen Parser für L1. Gehe für die L1-Instanz über den Baum. Übergeben Sie an jedem Knoten den übersetzten Text für L2 mit den String-Vorlagen von ANTLR.

Sie werden es schwer finden, genau zu entscheiden, was Sie generieren sollen, denn was Sie an jedem Punkt generieren, hängt vom Kontext ab (umgebende Deklarationen, Code und wie Sie sich entschieden haben, andere Sprachkonstrukte zu übersetzen). Betrachten wir übersetzen:

a+b 

Was wollen Sie generieren ist wahrscheinlich ziemlich unterschiedlich sein, wenn „a“ eine Zahl ist, gegenüber, wenn „a“ ist eine Zeichenfolge. Du kannst das nicht wissen, indem du das "a" in diesem Ausdruck betrachtest; Sie müssen die Deklaration für "a" finden und interpretieren (z. B. eine Symboltabelle erstellen und konsultieren).

Sie werden es schwer finden, guten Code zu generieren, da die Ausgabe (Zeichenfolgenvorlage) unverarbeiteter Text ist und Sie diesen Text nicht leicht interpretieren können, um ihn zu optimieren. Zum Beispiel vorstellen, den Sie übersetzen mögen:

x = y + "abc" 
x = x + "def" 

Einen einfachen Übersetzer (Anweisung für Anweisung) könnten produzieren (als reiner Text):

set(x,concat(y,"abc")) 
set(x,concat(x,"def")) 

Aber ein optimierende Übersetzer würde im Idealfall produzieren:

set(x,concat(y,"abcdef")) 

was es nur tun kann, indem man die Ausgabe prüft und erkennt, dass die Ausgabe optimiert werden kann. (OK, in diesem Beispiel könnten Sie die Eingabe zuerst optimieren, aber Sprachunterschiede können dies verhindern).

Dieses Problem motiviert ...

Method2: einen Parser für L1 bauen. Erstellen Sie einen Parser für L2. Gehe über den L1-Baum. Erstellen Sie an jedem Knoten einen L2-Baum mit den von ANTLR generierten Knotenkonstruktoren für L2.Sie werden aus den gleichen Gründen die gleiche schwere Zeit haben zu entscheiden, was zu generieren ist, aber jetzt, da Sie den L2-Baum haben, können Sie zumindest Code schreiben, um über den L2-Baum zu gehen und ihn zu optimieren, zB L2-zu implementieren -L2-Baum-Transformationen, die die obige Operation erreichen.

Wenn fertig, prettyprint the L2 tree. Sie können die String-Vorlagen von ANTLR für L2-Knoten verwenden, um zu helfen.

Andere Probleme mit reinen Parser-basierte Übersetzer

Beide Ansätze leiden unter einem allgemeinen Problem, dass reine Parser-Generatoren wie ANTLR haben: sie keine (leicht) Art und Weise zu collect context information needed to implement a good translator haben. [Dies gilt für beliebigen reinen Parser-Generator, den Sie auswählen].

Sie benötigen normalerweise auch andere Unterstützung, z. B. die Schöndruckmaschine. Das Leben ist auch bequemer, wenn Sie direkt die Transformationen aufschreiben können, zB

rule translate_square(t: term): product -> product 
     " \t**2 " => " \t * \t " 

anstatt das Schreiben von Code zu Fuß nach oben und unten dem Baum der Wurzel auf Figur ist „Macht“ Operator und das rechte Kind ist die Konstante 2. Sie müssen Hunderte von Bits Code schreiben, um alle Konstrukte in L1 zu übersetzen, wenn L1 eine nichttriviale Sprache ist, und dies wird prozedural ziemlich schnell langweilig.

Sie können also jeden Parsergenerator verwenden, um einen Übersetzer von einer Sprache in eine andere zu erstellen. Das ist sicherlich besser, als nur einen Übersetzer ohne einen Parser-Generator zu bauen, was Sie auch tun können (viele echte Compiler werden auf diese Weise erstellt). Aber während der Parser-Generator einigen hilft, macht er das Problem kaum aus. Sie benötigen viel mehr Maschinen und sollten viel mehr Aufwand investieren, als nur den Parser zum Laufen zu bringen (viele echte Compiler zahlen diesen Preis, um ihr Ergebnis zu erreichen).

+0

Wow. Danke für diese detaillierte Information! Aber ich denke, es wird einfacher für mich, da ich plane, L1 in AST von L2 zu parsen, was ich dann in Bytecode übersetzen werde -> L2-Kompilierung wird den generierten Code sowieso optimieren, denke ich. – lapots

Verwandte Themen