Ich würde gerne mit ANTLR beginnen, aber nachdem ich einige Stunden damit verbracht habe, die Beispiele auf der Website antlr.org zu überprüfen , kann ich immer noch kein klares Verständnis für den Grammatik-Java-Prozess erlangen.
Gibt es ein einfaches Beispiel, so etwas wie einen mit ANTLR implementierten Taschenrechner mit vier Operationen, der die Parserdefinition und den gesamten Java-Quellcode durchläuft?
Antworten:
Hinweis : Diese Antwort gilt für ANTLR3 ! Wenn Sie nach einem ANTLR4- Beispiel suchen , wird in diesen Fragen und Antworten gezeigt, wie Sie mit ANTLR4 einen einfachen Ausdrucksparser und Evaluator erstellen .
Sie erstellen zuerst eine Grammatik. Im Folgenden finden Sie eine kleine Grammatik, mit der Sie Ausdrücke auswerten können, die mit den vier grundlegenden mathematischen Operatoren erstellt wurden: +, -, * und /. Sie können Ausdrücke auch in Klammern gruppieren.
Beachten Sie, dass diese Grammatik nur eine sehr grundlegende ist: Sie behandelt keine unären Operatoren (das Minus in: -1 + 9) oder Dezimalstellen wie 0,99 (ohne führende Zahl), um nur zwei Mängel zu nennen. Dies ist nur ein Beispiel, an dem Sie selbst arbeiten können.
Hier ist der Inhalt der Grammatikdatei Exp.g :
(Parser-Regeln beginnen mit einem Kleinbuchstaben und Lexer-Regeln beginnen mit einem Großbuchstaben.)
Nach dem Erstellen der Grammatik möchten Sie einen Parser und einen Lexer daraus generieren. Laden Sie das ANTLR-Glas herunter und speichern Sie es im selben Verzeichnis wie Ihre Grammatikdatei.
Führen Sie den folgenden Befehl an Ihrer Shell / Eingabeaufforderung aus:
Es sollte keine Fehlermeldung angezeigt werden , und die Dateien ExpLexer.java , ExpParser.java und Exp.tokens sollten jetzt generiert werden.
Erstellen Sie diese Testklasse, um festzustellen, ob alles ordnungsgemäß funktioniert:
und kompiliere es:
und dann ausführen:
Wenn alles gut geht, wird nichts auf die Konsole gedruckt. Dies bedeutet, dass der Parser keinen Fehler gefunden hat. Wenn Sie ändern
"12*(5-6)"
in"12*(5-6"
und dann neu zu kompilieren und ausführen, sollte die folgende gedruckt werden:Okay, jetzt möchten wir der Grammatik ein bisschen Java-Code hinzufügen, damit der Parser tatsächlich etwas Nützliches tut. Das Hinzufügen von Code kann durch Platzieren
{
und}
Einfügen von einfachem Java-Code in Ihre Grammatik erfolgen.Aber zuerst: Alle Parserregeln in der Grammatikdatei sollten einen primitiven Doppelwert zurückgeben. Sie können dies tun, indem Sie
returns [double value]
nach jeder Regel Folgendes hinzufügen :Das bedarf keiner Erklärung: Von jeder Regel wird erwartet, dass sie einen doppelten Wert zurückgibt. Um nun mit dem Rückgabewert
double value
(der sich NICHT in einem einfachen Java-Codeblock befindet{...}
) aus einem Codeblock heraus "zu interagieren" , müssen Sie ein Dollarzeichen vorvalue
:Hier ist die Grammatik, aber jetzt mit dem hinzugefügten Java-Code:
und da unsere
eval
Regel jetzt ein Double zurückgibt, ändern Sie Ihre ANTLRDemo.java in Folgendes:Generieren Sie erneut (neu) einen neuen Lexer und Parser aus Ihrer Grammatik (1), kompilieren Sie alle Klassen (2) und führen Sie ANTLRDemo (3) aus:
und Sie sehen jetzt das Ergebnis des Ausdrucks
12*(5-6)
, der auf Ihrer Konsole gedruckt ist!Nochmals: Dies ist eine sehr kurze Erklärung. Ich ermutige Sie, im ANTLR-Wiki zu stöbern und einige Tutorials zu lesen und / oder ein bisschen mit dem zu spielen, was ich gerade gepostet habe.
Viel Glück!
BEARBEITEN:
Dieser Beitrag zeigt, wie Sie das obige Beispiel erweitern
Map<String, Double>
können, damit ein bereitgestellt werden kann, das Variablen im angegebenen Ausdruck enthält.Damit dieser Code mit einer aktuellen Version von Antlr (Juni 2014) funktioniert, musste ich einige Änderungen vornehmen.
ANTLRStringStream
zu werden , benötigtANTLRInputStream
benötigt, der zurückgegebene Wert auf Abwechslung vonparser.eval()
zuparser.eval().value
, und ich brauchte das entfernenWS
Klausel am Ende, weil Attributwerte wie$channel
nicht mehr in Lexer Aktionen erscheinen erlaubt.quelle
parser.eval()
passieren die Implementierungen von ? Das ist HIER oder im ANTLR3-Wiki nicht klar!eval
ist eine Parser-Regel, die a zurückgibtdouble
. Es gibt also eineeval()
Methode, die Sie für eine Instanz von aufrufen könnenExpParser
, wie ich in derANTLRDemo.main(...)
. ÖffnenExpParser.java
Sie nach dem Generieren eines Lexers / Parsers einfach die Datei und Sie werden sehen, dass es eineeval()
Methode gibt, die a zurückgibtdouble
.Das Mega-Tutorial von ANTLR von Gabriele Tomassetti ist sehr hilfreich
Es enthält Grammatikbeispiele, Beispiele für Besucher in verschiedenen Sprachen (Java, JavaScript, C # und Python) und viele andere Dinge. Sehr empfehlenswert.
EDIT: andere nützliche Artikel von Gabriele Tomassetti auf ANTLR
quelle
Für Antlr 4 ist der Java-Code-Generierungsprozess wie folgt: -
Aktualisieren Sie Ihren JAR-Namen im Klassenpfad entsprechend.
quelle
Unter https://github.com/BITPlan/com.bitplan.antlr finden Sie eine ANTLR-Java-Bibliothek mit einigen nützlichen Hilfsklassen und einigen vollständigen Beispielen. Es ist bereit, mit Maven verwendet zu werden und wenn Sie Eclipse und Maven mögen.
https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/main/antlr4/com/bitplan/exp/Exp.g4
ist eine einfache Ausdruckssprache, die Multiplikations- und Additionsoperationen ausführen kann. https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/test/java/com/bitplan/antlr/TestExpParser.java verfügt über die entsprechenden Komponententests.
https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/main/antlr4/com/bitplan/iri/IRIParser.g4 ist ein IRI-Parser, der in drei Teile unterteilt wurde:
https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/test/java/com/bitplan/antlr/TestIRIParser.java hat die Unit-Tests dafür.
Persönlich fand ich das der schwierigste Teil, um es richtig zu machen. Siehe http://wiki.bitplan.com/index.php/ANTLR_maven_plugin
https://github.com/BITPlan/com.bitplan.antlr/tree/master/src/main/antlr4/com/bitplan/expr
enthält drei weitere Beispiele, die für ein Leistungsproblem von ANTLR4 in einer früheren Version erstellt wurden. In der Zwischenzeit wurde dieses Problem behoben, wie der Testfall https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/test/java/com/bitplan/antlr/TestIssue994.java zeigt.
quelle
Version 4.7.1 war etwas anders: für den Import:
Beachten Sie für das Hauptsegment die CharStreams:
quelle