ABNF の Pygments lexer がない話と「ABNF Definition of ABNF」で混乱した話

一つ前の話なんかを書くには、RFC で使われてる ABNF を読む必要がどうしてもあって。

BNF、EBNF にはそれなりには慣れてるつもりだけど、RFC を読む習慣はそんなにはないので、細かいところが「たぶんそういう意味だろうな」とはわかっても、やっぱしちゃんとわかっとかないと「ワガラン」ところも出てくる。なので ABNF の RFCWikiPedia を交互に読んでてちょっと混乱した。

というのもね、こう言ってるわけ:

Unlike original BNF, angle brackets (“<“, “>”) are not required. However, angle brackets may be used around a rule name whenever their presence facilitates in discerning the use of a rule name.

でも「ABNF Definition of ABNF」でこう言ってて:

どの BNF 派生系も読めない人は、「a = b」を「a とは b である」を上から順に読む、とだけまずは憶えて。
1          rule           =  rulename defined-as elements c-nl
2                                 ; continues if next line starts
3                                 ;  with white space
4 
5          rulename       =  ALPHA *(ALPHA / DIGIT / "-")
6 
7          defined-as     =  *c-wsp ("=" / "=/") *c-wsp
8                                 ; basic rules definition and
9                                 ;  incremental alternatives

え? え? 自己矛盾してね?

と思ったら違った。すぐ上に書いてあったわ:

1. This syntax requires a formatting of rules that is relatively strict. Hence, the version of a ruleset included in a specification might need preprocessing to ensure that it can be interpreted by an ABNF parser.

2. This syntax uses the rules provided in Appendix B.

1.が完全に説明してるけど、1.を読まなくても 2. を読むだけでもいい。Appendix B (Core Rules) の定義に必要なので、ってことなのね。ABNF のフル定義ではない。なんだよ紛らわしい。

それはそうと、Pygments、EBNF については 2.0 になって書いてくれた人がいたのね。Bryan Davis さん、ですか。うぅ、ついでに ABNF も書いてくれりゃいーのに…。(オリジナル BNF もな。) EBNF は、なので今でも使えて:

 1 (* this is comment *)
 2 letter = "A" | "B" | "C" | "D" | "E" | "F" | "G"
 3        | "H" | "I" | "J" | "K" | "L" | "M" | "N"
 4        | "O" | "P" | "Q" | "R" | "S" | "T" | "U"
 5        | "V" | "W" | "X" | "Y" | "Z" ;
 6 digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
 7 symbol = "[" | "]" | "{" | "}" | "(" | ")" | "<" | ">"
 8        | "'" | '"' | "=" | "|" | "." | "," | ";" ;
 9 character = letter | digit | symbol | "_" ;
10  
11 identifier = letter , { letter | digit | "_" } ;
12 terminal = "'" , character , { character } , "'" 
13          | '"' , character , { character } , '"' ;
14  
15 lhs = identifier ;
16 rhs = identifier
17      | terminal
18      | "[" , rhs , "]"
19      | "{" , rhs , "}"
20      | "(" , rhs , ")"
21      | rhs , "|" , rhs
22      | rhs , "," , rhs ;
23 
24 rule = lhs , "=" , rhs , ";" ;
25 grammar = { rule } ;

こういう技術説明に不可欠なものは、やっぱし Syntax Highlighting があると断然説明しやすい。先天的に脳味噌フル活用して読む類のもんだから、読みにくさだけで疲れたくはない。

なんか ABNF lexer も欲しくなっちゃった。難しくはない、と思う。(ついでにいえば EBNF lexer は少し気に入らない。r'([a-zA-Z][\w \-]*)' 全部を「Keyword」トークンにしちゃうのはちょいと乱暴だ。)












追記
ABNF の lexer、書いた