ANTLR Parser mit manuellem Lexer

8

Ich migriere einen C # -basierten Programmiersprachencompiler von einem manuellen Lexer / Parser zu Antlr.

Antlr hat mir starke Kopfschmerzen bereitet, weil es normalerweise meistens funktioniert, aber dann gibt es die kleinen Teile, die nicht und sind unglaublich schmerzhaft zu lösen.

Ich habe entdeckt, dass die meisten meiner Kopfschmerzen durch die Lexer-Teile von Antlr und nicht durch den Parser verursacht werden. Dann bemerkte ich parser grammar X; und erkannte, dass ich vielleicht meinen manuell geschriebenen Lexer und dann einen von Antlr erzeugten Parser haben könnte.

Ich suche nach mehr Dokumentation zu diesem Thema. Ich denke, ein benutzerdefinierter ITokenStream könnte funktionieren, aber es scheint praktisch keine Online-Dokumentation zu diesem Thema zu geben ...

    
luiscubal 10.12.2010, 23:21
quelle

1 Antwort

7

Ich habe herausgefunden, wie. Es ist vielleicht nicht der beste Ansatz, aber es scheint zu funktionieren.

  1. Antlr-Parser erhalten einen ITokenStream -Parameter
  2. Antlr lexers sind selbst ITokenSource s
  3. ITokenSource ist eine deutlich einfachere Schnittstelle als ITokenStream
  4. Der einfachste Weg, ein ITokenSource in ein ITokenStream umzuwandeln, besteht darin, ein CommonSourceStream zu verwenden, das einen ITokenSource -Parameter
  5. erhält

Jetzt müssen wir nur noch zwei Dinge tun:

  1. Passen Sie die Grammatik so an, dass sie nur Parser ist
  2. Implementieren Sie ITokenSource

Das Anpassen der Grammatik ist sehr einfach. Entferne einfach alle Lexer-Deklarationen und vergewissere dich, dass du die Grammatik als parser grammar deklarierst. Ein einfaches Beispiel wird hier für die Bequemlichkeit geschrieben:

%Vor%

Beachten Sie, dass die folgende Datei class mygrammar anstelle von class mygrammarParser ausgibt.

Nun wollen wir einen "falschen" Lexer implementieren. Ich habe den folgenden Pseudocode persönlich benutzt:

%Vor%

Schließlich müssen wir TokenQueue definieren. TokenQueue ist nicht unbedingt notwendig, aber ich habe es aus Bequemlichkeit verwendet. Es sollte Methoden zum Empfangen der Lexer-Token und Methoden zum Ausgeben von Antlr-Tokens haben. Wenn also keine nativen Antlr-Token verwendet werden, muss eine Antlr-Token-Methode implementiert werden. Außerdem muss TokenQueue ITokenSource implementieren.

Beachten Sie, dass es sehr wichtig ist, die Token-Variablen korrekt zu setzen. Anfangs hatte ich einige Probleme, weil ich CharPositionInLine falsch berechnet habe. Wenn diese Variablen falsch festgelegt sind, kann der Parser fehlschlagen. Außerdem ist der normale Kanal (nicht versteckt) 0.

Das scheint für mich bisher zu funktionieren. Ich hoffe, dass andere es auch nützlich finden. Ich bin offen für Feedback. Insbesondere, wenn Sie einen besseren Weg finden, um dieses Problem zu lösen, zögern Sie nicht, eine separate Antwort zu veröffentlichen.

    
luiscubal 11.12.2010, 01:48
quelle

Tags und Links