コンパイラつく〜ろ〜♪ 4番JavaCCの記述

しばらくぶりですが、やっと知識的に整理ができたので
更新したいと思います。

前回記事pokotyamu.hatenablog.com

2番目の記事で導入までは終わらせているので、
今回は実際に使っていく時の書き方に対してまとめていきます。pokotyamu.hatenablog.com

1.JavaCCとは?

Java用のパーサジェネレーター兼スキャナジェネレーターです。
「.jj」の拡張子ファイルに文法規則を記述することで
入力に対して、文法の解析を行い、それぞれに適した処理を与えることが出来ます。

記述ファイルの内容としては、

option{
     //JavaCCのオプション
}
PARSER_BEGIN(パーサクラス名)
package パッケージ名;
import ライブラリ名;
public class パーサクラス名{
  //任意のJavaコード
}
PARSER_END(パーサクラス名)
//スキャナの記述
//パーサの記述

となっています。
この時optionsのみ省略することが可能です。

2.記述例

まずは、optionsから。

options{
 STATIC = false;//全部のメソッドをstaticでない状態で生成する
    JDK_VERSION = “JDK1.7"
}

生成されるコードに対して、様々な条件を記述することが出来ます。

PARSER_BEGINからPARSER_ENDまでは、
普通のJavaコードのように書くことできるので今回は省略します。

次にスキャナ
JavaCCの<>で囲まれている部分は非終端記号で、次のように記述をしていきます。

SKIP :{
          " "
        | "\r"
        | "\t"
        | "\f"
        | "\n"
}
TOKEN :{
          <STRING: "String">
        |  <IDENTIFIERS: ["a"-"z","A"-"Z","_"](["a"-"z","A"-"Z","_","0"-"9"])*>
        }

SKIPでは、マッチした文字列に対して、スルーすることが出来ます。
TOKENでは、マッチした文字列対してトークンを形成して返します。<トークン名:パターン>
という形で書かれます。
優先度は記述した順に判定されるため、
Stringという文字列を読み込ませた時
TOKENの記述が先にSTRINGでヒットするため、STRINGでマッチするかどうか?という判定を行います。
パターンについては正規表現で書くことができ、

0回以上の繰り返し
("a"-"z")*

1回以上の繰り返し
("a"-"z")+

前者もしくは後者
  ("a"-"z")
| ("A"-"Z")


最後にパーサの記述

Token processName():{
    Token t;
}{
    t = <IDENTIFIERS>{return t;}
}

これをjavaccコマンドにかけると、

final public Token processName() throws ParseException {
    Token t;
    t = jj_consume_token(IDENTIFIERS);
    {  if ("" != null) return t;}
        throw new Error("Missing return statement in function");
}

というコードを生成します。

この2つのコードを比較すると、

返り値 メソッド名():{
     変数の宣言
}{
     JavaCCのコード
     {Javaのコード}
}

このように書くことが出来ることが分かります。
JavaCCのコードにおいて<>で書かれるものについては、TOKENで記述したものが対応します。
よって、返り値として、TOKENを返すことが出来ます。

以上が、主な文法記述のまとめです。
次回は、自分が経験したエラーについてまとめていきたいと思います。