プログラム中でメールアドレスのパースは難しいとか言われているのでABNFのフル機能のほんものを実装してみた。
いろいろ詰め込んだ結果、JSONやJSON Pointer、JSON Patchまで簡単に実装できる。
IETFのRFCではABNFがよく使われている。メールだったりJSONなんかが有名で、IPアドレスやURLの書き方までABNFだったりする。
その割にあまり一般的なツールやライブラリとして出回っているのは数えるほどしかみたことないのでさっくりと作ってみた。
構造はParserを拡張してびるだー的なものを作って、びるだーでテキストからオブジェクトに変換するだけ。
ABNF自体もABNFで書かれているが、これは最初なのでビルダーだけで作る。
JSONなども書式を指定すればパーサができるので出力されるパーツを組み上げるビルダー的なところを組み込めばできあがり。
SoftLibRFC にRFCの一部ABNFをまとめているのでそれを使ってみるところの紹介。
必要なのは、SoftLibRFC,SoftLibABNF,SoftLib の3つ。SoftLibJSONは使わない。
現状ソースコードのみなので各自適度に使ってみたら。
net.siisise.abnf.rfc.IMF5322 というクラスがRFCのメールのABNFでRFC 5322ほぼそのまま。
IMF5322.angleAddr くらいがメールアドレスのみの定義にちょうどいいかな。
定義はREG という変数に格納されているのでpublicにしてないのはそこから取ってきてもいいしpublicにしてもいい。
boolean b = IMF5322.REG.ref("angle-addr").eq(メールアドレス);
くらいでbooleanな判定ができるかな。
個別のABNFはABNFクラス。
boolean eq(String) 完全一致 やboolean is(String) 先頭一致といったメソッドがあるのでお試しください。
Packet というクラスとあわせると、いろいろできるのだけど今回は省略。
ABNF同士をかけあわせて大きくしていくことができる。
まとめて使うには
ABNFReg に名前をつけて登録できるし、定義の中で参照も可能。
.rule(name,ABNF)と.rule(name,rule) .rule(rule) はどれもABNFの登録。
.ref(String)や.href(String)は名前で登録したABNFを持ってくる。
登録順序の関係が前後することがあるので登録していないものを取ってくるかこないかの違いがある。
.rulelist(String)で複数定義の一括登録も可能。改行が必要かもしれない。
拡張していくといつのまにかJSONも乗っかるので不思議。
SoftLibRFC
https://github.com/okomeki/SoftLibRFC
SoftLibABNF
https://github.com/okomeki/SoftLibABNF
SoftLib
https://github.com/okomeki/SoftLib
RFC 5234 ABNF
https://tools.ietf.org/html/rfc5234
RFC 8259 JSON
https://tools.ietf.org/html/rfc8259