ANTLRv3 を Maven から使う
ANTLR は Java で書かれたパーサジェネレータです。文法を定義したファイル (.g) からパーサのコードを自動生成してくれます。今回は ANTLR を antlr3-maven-plugin で Maven から使ってみます。
サンプル
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>study.maven.antlr.plugin</groupId> <artifactId>study-maven-antlr-plugin</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>study-antlr-helloworld</name> <url>http://maven.apache.org</url> <build> <plugins> <plugin> <groupId>org.antlr</groupId> <artifactId>antlr3-maven-plugin</artifactId> <version>3.4</version> <executions> <execution> <id>antlr3</id> <goals> <goal>antlr</goal> </goals> <phase>generate-sources</phase> <configuration> <outputDirectory>src/main/java</outputDirectory> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.2.1</version> <configuration> <mainClass>study.maven.antlr.plugin.Main</mainClass> </configuration> </plugin> </plugins> </build> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.antlr</groupId> <artifactId>antlr-runtime</artifactId> <version>3.4</version> </dependency> </dependencies> </project>
antlr3-maven-plugin の antlr3:antlr ゴールを Maven の generate-sources フェーズで実行するようにしています。これでソースをコンパイルする前にパーサが生成されます。また
続いて文法を定義したファイル (Hello.g) です。
grammar Hello; @header { package study.maven.antlr.plugin; } @lexer::header { package study.maven.antlr.plugin; } greet : 'Hello' COMMA 'World'; COMMA : ',';
このファイルを ${basedir}/src/main/antlr3/study/maven/antlr/plugin/Hello.g に配置します。antlr3-maven-plugin はデフォルトで ${basedir}/src/main/antlr3 ディレクトリ以下を読みます。
この状態でコンパイルするとパーサのコードが生成されます。
$ mvn clean compile
ソースディレクトリに HelloLexer.java, HelloParser.java ができているはずです。
最後に、パーサを使う実行クラス (Main.java) です。
package study.maven.antlr.plugin; import org.antlr.runtime.ANTLRStringStream; import org.antlr.runtime.CharStream; import org.antlr.runtime.CommonTokenStream; public class Main { public static void main(String[] args) throws Exception { CharStream cs = new ANTLRStringStream(args[0]); HelloLexer lexer = new HelloLexer(cs); CommonTokenStream tokens = new CommonTokenStream(); tokens.setTokenSource(lexer); HelloParser parser = new HelloParser(tokens); parser.greet(); int errors = parser.getNumberOfSyntaxErrors(); if (errors > 0) { System.out.println("ERROR!"); } else { System.out.println("SUCCESS!"); } } }
HelloLexer, HelloParser を使って標準入力をパースしています。
パースに成功した場合
$ mvn exec:java -Dexec.args="Hello,World" (…省略…) SUCCESS! [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 0.669s [INFO] Finished at: Tue Feb 21 23:06:46 JST 2012 [INFO] Final Memory: 3M/81M [INFO] ------------------------------------------------------------------------
パースに失敗した場合
$ mvn exec:java -Dexec.args="Bye,World" (…省略…) line 1:0 no viable alternative at character 'B' line 1:1 no viable alternative at character 'y' line 1:2 no viable alternative at character 'e' line 1:3 missing 'Hello' at ',' ERROR! [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 0.658s [INFO] Finished at: Tue Feb 21 23:08:02 JST 2012 [INFO] Final Memory: 3M/81M [INFO] ------------------------------------------------------------------------