Registrar Script の BNF が腐っている件

Boost.Spirit で何か試しに解析してみようと思って、ちょうどパース ツリーについて (ATL)辺りに BNF で書かれた文法があったので、これを使ってみることにしてみた。

<root key>{<registry expression>}+
<root key> ::= HKEY_CLASSES_ROOT | HKEY_CURRENT_USER |
               HKEY_LOCAL_MACHINE | HKEY_USERS |
               HKEY_PERFORMANCE_DATA | HKEY_DYN_DATA |
               HKEY_CURRENT_CONFIG | HKCR | HKCU |
               HKLM | HKU | HKPD | HKDD | HKCC
<registry expression> ::= <Add Key> | <Delete Key>
<Add Key> ::= [ForceRemove | NoRemove | val]<Key Name>
              [<Key Value>][{< Add Key>}]
<Delete Key> ::= Delete<Key Name>
<Key Name> ::= '<AlphaNumeric>+'
<AlphaNumeric> ::= any character not NULL, i.e. ASCII 0
<Key Value> ::== <Key Type><Key Name>
<Key Type> ::= s | d
<Key Value> ::= '<AlphaNumeric>'

しかしこれ、おかしいところがありすぎ。


1.

<root key>{<registry expression>}+

これ、優先順位がどうやってあるのか知らないけど、括弧で優先順位を付けるとすれば、

(<root key>{<registry expression>})+

こうなるのが正しい。


2.

<registry expression> ::= <Add Key> | <Delete Key>
<Delete Key> ::= Delete<Key Name>

え、Delete はルートキーの一つ下のキーだけしか指定できないんですか?


3.

<Add Key> ::= [ForceRemove | NoRemove | val]<Key Name>
              [<Key Value>][{< Add Key>}]

val で指定するものは、キーではなく値なので、最後の {} を指定することは不可能。


4.

<Add Key> ::= [ForceRemove | NoRemove | val]<Key Name>
              [<Key Value>][{< Add Key>}]

この文法だと、

val 'Hoge' = s'hoge'
val 'Hoge2' = s'hogehoge'

という風に、連続してキーや値を書くことが出来ません(実際は出来る)。


5.

<Key Name> ::= '<AlphaNumeric>+'

'' で囲まれていなくても名前を指定することが出来ます。

ForceRemove HogeKey
{
    val Hoge = s'hoge'
}

てな感じで。
の中の は省略することは無理かな?
試してないからわかんない。


6.

<AlphaNumeric> ::= any character not NULL, i.e. ASCII 0
<Key Name> ::= '<AlphaNumeric>+'

が ' という文字だったらおかしくなるんじゃ?
あとエスケープシーケンスとか使えないのかな?要調査。


7.

<Key Value> ::== <Key Type><Key Name>
<Key Value> ::= '<AlphaNumeric>'

意味わかんないから。


8.

<Key Type> ::= s | d

m と b も指定することが可能です。
最初にこれを書いた当時は無かったんだろうな...。



さすがの Boost.Spirit も、BNF が間違ってたら解釈できませぬ。
レジストラスクリプトを解釈するためには、まず正しい BNF を作るところから始めないとダメというわけですな。



追記:
いや待てよ、1.の定義が例えば

<root key>{<registry expression>+}

こう書きたかったのだとすれば、

<root key>{(<Add Key> | <Delete Key>)+}

となるので、4.は解決できそう。
しかしルートキーが複数指定できるという定義が無くなるのでどのみちダメな訳ですが。