ANTLRのお勉強

DSLを作りたいので、ANTLRのお勉強をしています。 ANTLRのサイトではどのドキュメントから読んでいけば良いのかわかりにくい部分があるので、整理してみました。
使いこなしているわけではないので、誤り等はご容赦下さい。

ANTLR 概要

ANTLRとは?

ANTLRはパーサジェネレータと呼ばれるもので、「言語設計者が定義した文法から、言語の文法に従って記述されたコードを解析するパーサを生成する」ツールです。
DSL(ドメイン特化言語=特定の目的のためのミニ言語)を作成するための重要なツールになります。
Javaをメインの言語として開発されています。

ANTLRでは、以下を行うことができます。

  • 字句解析・構文解析の文法ファイルからの字句解析器・構文解析器の生成 文法ファイルを記述すると、そこから字句解析器・構文解析器クラスを生成してくれます。
  • 木文法からの抽象構文木の走査器の生成 木文法と呼ばれるものを記述すると、抽象構文木DSLコードを解析し木構造にしたもの)の走査器クラスを生成してくれます。

ANTLRの凄いところ

  • 字句解析器・構文解析器・走査器は、Javaがメインですが、C#C++等のコードとしても出力できます。
  • コードにエラーがある場合、ある程度わかりやすくエラーを出力してくれます(たぶん)。
  • StringTemplateというテンプレートエンジンと統合されているため、DSLからのコード生成ができます。
  • ANTLRWorksというGUIで、文法の作成・デバッグをサポートしてくれます。

エラー出力なども含めて字句解析器・構文解析器・走査器を手で記述すると、気の遠くなるような作業になりそうですが、ANTLRでそれらを省力化することができます。

DSL開発者は何をすればいい?

DSL開発者は、ANTLRを使ってDSLの開発を行うときには、以下のことをすれば良いです。

  • DSLの文法を定義する
  • ANTLRを使って、文法から字句解析器・構文解析器・走査器のクラスを出力する。
  • 字句解析器・構文解析器・走査器を呼び出すメソッドを作成し、コンパイルする。

以上で、DSLプログラムが開発できたことになるので、DSLコードを記述してプログラムを走らせると、DSLコードを解析して思いのままのことができます。(たぶん)

ANTLRを使ってみる

JavaANTLRを使ってみる

下の方に記述した参考文献のGetting Startedのリンクに沿って、ファイルを入手し設定して行くのが良いと思います。 私はJavaANTLRを使っていないので、説明は省略します。

C#ANTLRを使ってみる

下の方に記述した参考文献のGetting Started C#のリンクに沿って、ファイルを入手し設定して行くのが良いと思います。

ANTLRの実行は、以下の2つのフェーズに分かれるのですが、

  1. grammerファイルから、ANTLRによりlexer, parserクラスを作成する
  2. メインファイルから、作成したlexer, parserクラスを呼び出し、DSLコードを解析する

以下のようにいくつか方法があります。

  1. コマンドラインからlexer, parserクラスを作成し、Visual Studioにそれらのクラスを追加し実行する
  2. ANTLRWorksを用いてlexer, parserクラスを作成し、Visual Studioにそれらのクラスを追加し実行する
  3. Visual Studio機能拡張を用いて両方を同時に行う

Visual Studio機能拡張は楽なのですが、設定方法にひと手間必要だったり、デバッグがややしづらかったりします。ANTLRWorksも、C#用の出力をする場合にはdebugが行いにくいなどの微妙な点があるため、一長一短です。
私は現在のところ2.の方法を用いています。

ポイント

つまづくポイントや、ドキュメントからはなかなかわかりにくいことを書きます。

[C#]Visual Studio 機能拡張を使ったときにコンパイルができない

ANTLR Language Support v1.0.11で確認。
「呼び出しのターゲットが例外をスローしました。」なるエラーが出てコンパイルできない。
これは、以下にあるように、Antlr\Tool\Templates\messages\languagesのen.stgをコピーして名前をja.stgに変更すればOK。
Something Wrong in Antlr3CSharpReleases 3.4?
http://antlr.1301665.n2.nabble.com/Something-Wrong-in-Antlr3CSharpReleases-3-4-td6895968.html

[C#]エラーを出力しない!

ANTLR3.Runtime v3.4.1.9004で確認。
Parserを作成してDSLコードを解析しようとしたときに、No viable alternativeなどのエラーを出力してくれません。これでは、入力したDSLコードがあっているかわからないので、使い物になりません。
http://stackoverflow.com/questions/8525009/antlr-not-emitting-error-messages-on-invalid-input にあるとおり、
lexer.TraceDestination = Console.Out;
parser.TraceDestination = Console.Out; を追加すると出力してくれます。

文法の種類って何があるの?

ANTLRの文法には、以下の種類がある。

  • lexer grammer(lexer grammer で始まる)字句解析器
  • parser grammer(parser grammer で始まる)構文解析
  • tree grammer(tree grammer で始まる)木文法-抽象構文木の走査を行うもの
  • combined grammer(grammer で始まる)字句解析器+構文解析

通常は、combined grammer(とtree grammer)を使えば良いはず。

走査のやり方

コード解析できるだけでは意味が無く、解析したコードをもとにクラスを出力したり、抽象構文木を走査して適宜画面出力したり、といったことが必要になる。
主に以下の2種類の方法で走査を行うことができる。

後者の方がひと手間増えるが、走査を抽象構文木の作成と走査の2つのパーツに分けることができ、スケーラブルな方法といえる。

1.構文解析時にアクションを用いて走査等を行う方法
2.構文解析により抽象構文木(AST)を作成し、木文法により走査を行う方法

参考文献

Getting Started

まずは、以下のGetting Startedから読むのが良さそう
http://www.antlr.org/wiki/display/ANTLR3/FAQ+-+Getting+Started

次に、Getting Startedで紹介されているTutorialsや例を読んでいくと良さそう。
http://www.antlr.org/wiki/display/ANTLR3/Five+minute+introduction+to+ANTLR+3
http://www.antlr.org/wiki/display/ANTLR3/Quick+Starter+on+Parser+Grammars+-+No+Past+Experience+Required
http://www.ociweb.com/jnb/jnbJun2008.html
http://www.antlr.org/wiki/display/ANTLR3/Parsing+XML
http://www.antlr.org/wiki/display/ANTLR3/Fig+-+Generic+configuration+language+interpreter

また、以下のページの下部にExampleがある。
http://www.antlr.org/download.html

お金があれば、ANTLRv3の参考書を買ってみるのも良いかも。
http://www.pragmaticprogrammer.com/titles/tpantlr/index.html
全部を読むのはきついが、以下の章はとても参考になった。

  • chapter3の電卓計算をするような言語の解析
  • chapter8.2のC-言語(簡易版C言語)の解析

Getting Started C#

C#で始めるには、以下から読んでいくと良いと思います。
http://www.antlr.org/wiki/display/ANTLR3/Antlr+3+CSharp+Target
http://www.antlr.org/wiki/display/ANTLR3/Antlr3CSharpReleases
Antlr3CSharpReleasesのVisual Studio and the ANTLR C# Targetのリンクから、Visual Studio機能拡張を入手できます。

その他役に立ちそうなドキュメント

http://www.antlr.org/wiki/display/ANTLR3/ANTLR+Cheat+Sheet
http://www.antlr.org/wiki/display/ANTLR3/ANTLR+v3+documentation
http://www.antlr.org/wiki/display/ANTLR3/ANTLR+v3+printable+documentation
http://www.stringtemplate.org/

その他役に立ちそうなドキュメント C#

http://stackoverflow.com/questions/4396080/antlr-3-3-c-sharp-tutorials
http://www.manuelabadia.com/blog/CategoryView,category,ANTLR.aspx
http://www.lextm.com/search/label/ANTLR
http://www.codeproject.com/Articles/18880/State-of-the-Art-Expression-Evaluation
http://d.hatena.ne.jp/runicalp/searchdiary?word=*[ANTLR]

日本語のドキュメント

cx5software C++ANTLRを使う
http://cx5software.com/article_antlr/
ここが一番わかりやすいか。
Unlimited Island ANTLRを使ってみる
http://www.limy.org/program/java/antlr/step1.html
http://www.limy.org/program/java/antlr/step2.html
竹本 浩のページ antlr
http://www.pwv.co.jp/~take/TakeWiki/index.php?FrontPage#q1c6f434
cloverrose ANTLR
https://sites.google.com/site/cloverplusrose/gou-wen-jie-xi
zp's note ANTLRかわいいよANTLR
http://d.hatena.ne.jp/zpx/20110502/1304416560

DSL関連書籍

一緒に読むと理解が深まりそう。というか本を1回読んだだけではわからなくて、本⇔ANTLRを行ったり来たりして理解が深まってくる感じ。
言語実装パターン ―コンパイラ技術によるテキスト処理から言語実装まで
http://www.amazon.co.jp/dp/4873115329
ドメイン特化言語 パターンで学ぶDSLのベストプラクティス46項目
http://www.amazon.co.jp/dp/4864010471
2週間でできる! スクリプト言語の作り方
http://www.amazon.co.jp/dp/4774149748