コンパイラつく〜ろ〜♪ 4番JavaCCの記述
しばらくぶりですが、やっと知識的に整理ができたので
更新したいと思います。
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を返すことが出来ます。
以上が、主な文法記述のまとめです。
次回は、自分が経験したエラーについてまとめていきたいと思います。