SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

JavaCCでスクリプト言語を作成する

JavaCCでスクリプト言語を作成する 第1回

JavaCCとJJTreeを使ったプログラムの構築方法


処理プログラム

 こうして生成したパーサーを利用するプログラムを作成します。

codezine/hello/Hello.java
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を使わずにプログラムを組んだほうが楽ですが、もう少し複雑な文法になってくるとメリットがでてきます。

 次回は、文法定義ファイルの構文を説明しながら、もう少し複雑な例を挙げていこうと思います。

修正履歴

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
JavaCCでスクリプト言語を作成する連載記事一覧

もっと読む

この記事の著者

きしだ なおき(キシダ ナオキ)

フリーのプログラマ。Javaでの業務アプリケーションからC++での小型端末などさまざまなプログラムを開発。また、入門者向けのJavaセミナーなども行う。そのセミナーで鍛えられたテキストが、著書である「創るJava」。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/367 2006/08/09 11:26

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー