処理プログラム
こうして生成したパーサーを利用するプログラムを作成します。
package codezine.hello; import codezine.hello.parser.*; public class Hello implements HelloParserVisitor{ public static void main(String[] args){ try { HelloParser parser = new HelloParser(System.in); Node node = parser.Hello(); Hello visitor = new Hello(); node.jjtAccept(visitor, null); } catch(TokenMgrError ex){ System.out.println("字句解析エラー:" + ex.getMessage()); } catch (ParseException ex) { System.out.println("構文解析エラー:" + ex.getMessage()); } } public Object visit(SimpleNode node, Object data) { //ここには来ない return null; } public Object visit(ASTHello node, Object data) { String word = node.jjtGetChild(0).jjtAccept(this, null) .toString(); System.out.println("こんにちは " + word +"!!"); return null; } public Object visit(ASTJavaCC node, Object data) { return "ステキJavaCC"; } public Object visit(ASTJJTree node, Object data) { return "イカスJJTree"; } }
このプログラムではHelloParserVisitorインターフェイスを実装しています。HelloParserVisitorインターフェイスでは、各ノードに対応するvisitメソッドが定義されていて、それぞれのノードが処理されるときに呼び出されます。
mainメソッドでは、まずHelloParserクラスのコンストラクタにReaderオブジェクトを渡してパーサーオブジェクトを生成します。
HelloParser parser = new HelloParser(System.in);
次に、パーサーから構文解析の入り口になるノードのメソッドを呼び出します。
Node node = parser.Hello();
そして、そのノードに対してjjtAcceptメソッドを呼び出すと処理が行われます。
Hello visitor = new Hello(); node.jjtAccept(visitor, null);
字句解析でエラーが出たときにはTokenMgrError例外、構文解析でエラーになったときにはParseException例外が発生するので、それぞれを捕捉して適切な処理を行います。ここではメッセージを表示しています。
TokenMgrErrorの方は検査例外ではなく、例外処理をしなくてもコンパイルを通すことができますが、例外処理をした方がよいと思います。
コンパイル
コンパイルには、通常のJavaプログラムと同様にjavacを使うのですが、ant構築ファイルにコンパイルタスクを記述してあるので、こちらを使います。
C:\java\product\CodeZine>ant compile
Buildfile: build.xml
init:
compile:
[javac] Compiling 16 source files to C:\java\product\CodeZine\bu
ild\classes
[javac] 注: 入力ファイルの操作のうち、未チェックまたは安全ではな
いものがあります。
[javac] 注: 詳細については、-Xlint:unchecked オプションを指定し
て再コンパイルしてください。
BUILD SUCCESSFUL
Total time: 1 second
JavaCCが生成したファイルでVectorを利用しているので警告がでますが、問題はありません。
動作確認
それでは動かしてみます。
実行して「hello javacc」と入力すると「こんにちは ステキJavaCC!!」と表示されます。
C:\java\product\CodeZine\build\classes>java codezine.hello.Hello hello javacc こんにちは ステキJavaCC!!
「hello jjtree」と入力すると「こんにちは イカスJJTree!!」と表示されます。
C:\java\product\CodeZine\build\classes>java codezine.hello.Hello hello jjtree こんにちは イカスJJTree!!
「hello java」と入力した場合は、「java」というトークンが定義されていないので字句解析エラーが出ます。
C:\java\product\CodeZine\build\classes>java codezine.hello.Hello hello java 字句解析エラー:Lexical error at line 1, column 11. Encountered:"\r" (13), after : "java"
「javacc」と入力した場合は、文法上「hello」が先に来る必要があるので構文解析エラーが出ます。
C:\java\product\CodeZine\build\classes>java codezine.hello.Hello
javacc
構文解析エラー:Encountered "javacc" at line 1, column 1.
Was expecting:
"hello" ...
このように、構文の解釈と、それに従った処理が実行されることを確認できます。
まとめ
今回はJavaCC/JJTreeでの処理について構築方法を中心に説明しました。
ここで挙げたような簡単な例の場合はJavaCC/JJTreeを使わずにプログラムを組んだほうが楽ですが、もう少し複雑な文法になってくるとメリットがでてきます。
次回は、文法定義ファイルの構文を説明しながら、もう少し複雑な例を挙げていこうと思います。

ild\classes
[javac] 注: 入力ファイルの操作のうち、未チェックまたは安全ではな