Apache Maven – ANTLR Integration (Permalink)

Im 4ten Teil der Serie über Maven (Teil 1, Teil 2, Teil 3) soll gezeigt werden, wie Maven genutzt werden kann, um im Build-Prozess ANTLR-Dateien zu integrieren.

ANTLR

ANTLR steht für "ANother Tool for Language Recognition". ANTLR generiert aus den geeigneten Definitionen Lexer, Parser oder TreeParser. Als Zielsprache ist ANTLR nicht auf Java festgelegt, sondern generiert auch Code für C, C++, Python, JavaScript und weitere. Für uns ist hier die Ausgabe natürlich nur in Java interessant.

Erweiterung der pom.xml

Um ANTLR in einem Projekt verwenden zu können, muss die pom.xml an 2 Stellen geändert werden. Zum einen muss eine neue Abhängigkeit zur ANTLR-Runtime definiert werden. Dies passiert im unteren Abschnitt. Damit stehen die ANTLR-Klassen wie bei jeder anderen Dependency bereit.

Soll Maven jedoch noch automatisch aus ANTLR-Grammatikdateien (*.g) entsprechende Java-Klassen erstellen, so ist eine Erweiterung des Build-Vorgangs notwendig. Dazu wird im oben Bereich das antlr3-maven-plugin eingebunden.

<project ...>
    ...
    <build>
        <plugins>
            ...
            <plugin>
                <groupId>org.antlr</groupId>
                <artifactId>
                    antlr3-maven-plugin
                </artifactId>
                <version>3.1.3-1</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>antlr</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            ...
        </plugins>
    </build>
    ...
    <dependencies>
        ...
        <dependency>
            <groupId>org.antlr</groupId>
            <artifactId>antlr-runtime</artifactId>
            <version>3.2</version>
            <type>jar</type>
       </dependency>
        ...
    </dependencies>
</project>

Grammatik für Ausdrücke als Beispiel

Die folgende Beispielgrammatik (b1.g) muss im Verzeichnis src/main/antlr3/package/b1 abgelegt werden. das ANTLR-Plugin durchsucht das Verzeichnis src/main/antlr3/package. Alle .g-Dateien innerhalb des Verzeichnisbaums werden von ANTLR übersetzt und im Verzeichnisbaum target/generated-sources/antlr3/package gespeichert. Im weiteren Verlauf des Build-Prozesses sind diese Klassen dann im Classpath und so normal verwendbar.

// Name der Grammatik
grammar b1;

// einfache, feste Tokens
tokens {
    PLUS    = '+' ;
    MINUS   = '-' ;
    MULT    = '*' ;
    DIV = '/' ;
}

@header {
        package b1;
}

@lexer::header {
        package b1;
}

ausdruck:
        term ( ( PLUS | MINUS )  term )* ;

term    :
        faktor ( ( MULT | DIV ) faktor )* ;

faktor  :
        ZAHL ;

ZAHL    :
        (DIGIT)+ ;

WHITESPACE :
        ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+
                { $channel = HIDDEN; } ;

fragment DIGIT  :
        '0'..'9' ;

Aus dieser Grammatik-Datei entstehen 2 Klassen:

  • b1Lexer.java
  • b1Parser.java

Der Lexer zerlegt die Eingabe in sog. Tokens, von denen der Parser prüft, ob sie einen gültigen Satz ergeben. In unserem Fall würde "5 * 4 + 3" im Lexer zu "ZAHL MULT ZAHL PLUS ZAHL" und im Parser zu einem sog. Parsebaum "((ZAHL MULT ZAHL) PLUS ZAHL)".

Résumé

Eine Integration von ANTLR in den Build-Prozess über Maven ermöglicht eine wesentlich einfachere Entwicklung, da händische Zwischenschritte (Erzeugen von Lexer, Parser und/oder Baumparser) entfallen können. Durch anschließende Tests wird dabei automatisch überprüft, ob ein Build erfolgreich ist oder nicht.

Update 5. Juni 2018

Die Quellen zu diesem Artikel findet man jetzt unter https://gitea.lusiardi.de/jlusiardi/MavenAntlrIntegration. Maven 3.3 kann in einem Docker-Container mit folgendem Kommando zum Build benutzt werden:

docker run -it --rm -v "$(pwd)":/usr/src/mymaven   
 -w /usr/src/mymaven maven:3.3-jdk-8 mvn clean install

Update 27. Mai 2023

Wie in den vorangegangen Teilen wurden auch hier Updates verschiedener Versionen vorgenommen.