argius note

プログラミング関連

JavaでJVM言語を作ってみる(1) - 環境を準備する

これまでも極簡単な処理系を作ってみたことはありますが、いずれもインタプリタで実用的ではないものでした。
今回も、本格的なものを作る気は今のところはありません。
ですので、題名は正確には、JVM言語を作る環境を準備する、と言ったところでしょうか。
独自の言語を設計し、それを他の言語にコンバートせずに、直接Javaバイトコードを生成する処理系を作る方法について、大雑把にまとめてみます。


最初のゴール

処理系について

処理系は、一般的には

字句解析器ジェネレータ →(生成)→ 字句解析器
構文解析器ジェネレータ →(生成)→ 構文解析器
プログラミング言語のコード → 字句解析器 → 構文解析器 → コンパイラ・インタプリタ

となります。※追記(2012-03-07):全体的に字句解析と構文解析が逆になっていたので直しました。(なんということでしょう!)
上記の各ジェネレータは、解析を行うプログラム(パーサ)を生成するためのツールで、文法規則を記述したファイルを入力すると、その文法に従ってコードを解析する解析器のプログラム(関数)を出力してくれるというものです。パーサジェネレータとも呼ばれます。
字句解析器(レキシカルアナライザ、パーサ)は、その言語の文法で定められたトークンに分解します。
構文解析器(シンタクティックアナライザ)は、トークンを読み取って文を解析し、構文木などを生成したりします。そして、解析結果に従って処理を実行(インタプリタが行う)するか、実行するコードを出力(コンパイラが行う)します。
C言語では字句解析器ジェネレータにyacc構文解析器ジェネレータにlexを使って作るのが(たぶん今でも)一般的で、LL言語なんかはC言語処理系はそれで作られていたりします。


ここではすべてJava関連のツールやライブラリで賄います。解析器ジェネレータはいくつかありますが、JavaCCを使います。字句解析器ジェネレータは未定。
さらに、バイトコード生成ツールとして、Apache Commons BCELを使います。
なお、コンパイラ構文解析器の解析結果をバイトコードに翻訳するもので、インタプリタは、構文解析器の解析結果を動的に評価する環境です。(GHCとGHCiを意識しています。)

仮構築

言語の設計を行うには、どのように処理系が作られているかをある程度把握しなければなりません。基盤となる環境で実現不可能なものを設計してしまったら、実際に作ろうとしたときには手遅れです。
ですので、まずは極力すぐに形になるものから作っていき、それを少しずつ改築・増築していくのが良いでしょう。本格的な設計を行うのは、これらをマスターしてからでないと難しいと思います。
ちなみに私もマスターしているわけではないので、ほとんど初心者です。試行錯誤でやっていきます。


もうひとつ。Java言語を介さずにバイトコードを構築するには、JVMの動きを理解しなければなりません。
そこで、まず最初に簡単なプログラムをJava言語を使わずに*1作ってみます。


(つづく)

*1:Javaライブラリは使います。"*.javaを書かずに"という意味です。