JavaCC (Java Compiler Compiler) は再帰下降型構文解析を行う Java プログラムを生成する構文解析部生成器 (parser generator) です。 JavaCC はマイクロ構文規則およびマクロ構文規則を記述したソースコードから構文解析器を生成します。
javacc コマンドの引数にマイクロ構文規則およびマクロ構文規則を記述したファイルを指定すると、 その構文規則を元に構文解析器が生成されます。
以下では javacc.zip を例として javacc の使い方を説明します。 javacc.zip に入っている サンプル構文規則 parse.jj およびサンプル原始言語ファイル sample0.k を用いて javacc により以下の手順でコンパイルできます。
$ cd ~/javacc/kc $ javacc parse.jj Java Compiler Compiler Version 5.0 (Parser Generator) (type "javacc" with no arguments for help) Reading from file parser.jj . . . Note: UNICODE_INPUT option is specifiled. Please make sure you create the parser/ lexer using a Reader with the correct character encodng. File "TokenMgrError.java" does not exist. Will create one. File "ParserException.java" does not exist. Will create one. File "Token.java" does not exist. Will create one. File "SimpleCharStream.java" does not exist. Will create one. Parser generated successfully. $ cd .. $ javac kc/Parse.java $ java kc.Parse sample0.k finished
1行目の javacc コマンドにより、 構文解析を行う Java プログラム Parser.java (とそれに付随する Java プログラム) が生成されます。 javac コマンドで ParserCode.java をコンパイルをした後、java コマンドで sample0.k を引数として Parser.class を実行すると構文解析を行うことができます。 (Parser.java は構文解析部のみでコード生成部はありません)
parse.jj にコード生成部を埋め込んだものが サンプル構文規則 parseCode.jj です。 こちらを javacc でコンパイルすると以下の結果が得られます。
$ cd ~/javacc/kc $ javacc parseCode.jj $ cd .. $ javac kc/ParseCode.java $ java kc.ParseCode sample0.k finished $ cat OpCode.asm PUSHI 0 INPUT ASSGN REMOVE PUSH 0 BEQ 10 PUSH 0 PUSHI 2 MUL OUTPUT HALT $ ./vsm 2 4
javacc により、 parserCode.jj から ParserCode.java が生成されます。 javac でコンパイルをした後、 sample0.k を引数として ParserCode.class を実行するとアセンブリコードが OpCode.asm に出力されます。 出力されたアセンブリコードは vsm インタプリタで実行できます。
jj プログラム先頭部分のオプション指定で DEBUG_PARSER の値を true にすると 生成した Java プログラムの実行時にトレースが表示されます。
$ cd ~/javacc/kc $ javacc parse.jj $ cd .. $ javac kc/Parser.java $ java kc.Parser sample0.k Call: Main Consumed token: <"main" at line 1 column 1> Consumed token: <"(" at line 1 column 6> Consumed token: <")" at line 1 column 7> Consumed token: <"{" at line 1 column 9> Call: Decl Consumed token: <"int" at line 2 column 9> Call: Name Consumed token: <: "i" at line 2 column 13> Return: Name Consumed token: <";" at line 2 column 14> Return: Decl Call: State Call: Assgn Consumed token: < : "i" at line 3 column 9> Consumed token: <"=" at line 3 column 11> Call: Exp Call: Term Call: Factor Consumed token: <"input" at line 3 column 13> Return: Factor Return: Term Return: Exp Consumed token: <";" at line 3 column 18> Return: Assgn Return: State Call: State Call: If Consumed token: <"if" at line 4 column 9> Consumed token: <"(" at line 4 column 12> Call: Exp Call: Term Call: Factor Consumed token: < : "i" at line 4 column 13> Return: Factor Return: Term Return: Exp Consumed token: <")" at line 4 column 14> Call: State Call: Output Consumed token: <"output" at line 4 column 16> Consumed token: <"(" at line 4 column 23> Call: Exp Call: Term Call: Factor Consumed token: < : "i" at line 4 column 25> Return: Factor Consumed token: <"*" at line 4 column 26> Call: Factor Consumed token: < : "2" at line 4 column 27> Return: Factor Return: Term Return: Exp Consumed token: <")" at line 4 column 29> Consumed token: <";" at line 4 column 30> Return: Output Return: State Return: If Return: State Consumed token: <"}" at line 5 column 1> Consumed token: < at line 5 column 3> Return: Main finished
javacc は構文解析部以外に利用することもできます。 例として計算機の作成を挙げておきます。 サンプル構文規則 calc.jj をコンパイルし、 生成された Java プログラム Calc.java を sampleExp.txt を引数として実行すると以下の結果が得られます。
$ cd ~javacc/calc/ $ javacc calc.jj $ cd .. $ javac calc/Calc.java $ java calc.Calc sampleExp.txt 110 -22 2