ちょっと実用的なコマンドラインパーサを作ろう、と思っているわけです。C# で。
困ったことに、コマンドラインパーサってのはどんなアプリでも利用可能ですから、こういうものを作ろうと思い立ってしまうと、これが出来上がるまで他のどんなアプリも作りたくなくなります。俺の悪い癖です。
で、悩んでいるのが、
- 既存のアプリのコマンドラインの仕様を変えずに移植できるように柔軟性を持たせるか
- このパーサライブラリを使う以上は使用可能なコマンドラインの仕様にある程度の制限があるのも止むなしとするか
ということ、とか。
まぁほら、後者の方が作るのは簡単なんですけど、前者ができるならそれに越したことは無いじゃない? みたいな。
あとは、パラメータを指定するにしても、世の中にはいろんな方式のアプリがあるわけですよ。
例えば、オプション「/foo」にパラメータ「bar」を指定するのでも、
- /foo bar
- /foo:bar
- /foobar
なんてのがあります。
2と3は技術的にはあまり違いはありません。見た目的には2の方が好きです。
が、1と2には大きな違いがあります。
コマンドラインは Main に文字列配列として渡されますが、1 は /foo と bar が別の要素になるのに対し、2 は単一の要素になります。
当然、1の方が解析は面倒です。「bar」を処理するときに、その前の要素が「/foo」であるか、そうでないかでは意味が違ってくるからです。
このため、コマンドラインパーサは、簡易な状態遷移機械ということになります。
ちなみに、3つの中では見た目的に1が一番好きです。
このように、コマンドの順序を意識しなければならないこともあれば、順序はどうでもいい場合もあります。
例えば、オプション /hoge と /hage があるとき、以下の2つは
どっちでもいいじゃないですか。
もっと複雑な例になると、/foo:X=1,Y=2,Z=3 なんていう例も考えられます。もちろん、/foo:Z=3,X=1,Y=2でも同じ意味でなければなりません。
正直、こんなのをパースするのは面倒です。
で、正規表現を使っちゃえばいいじゃないか、と思い立ったわけです。キャプチャしてくれますから。
ただですね、上のは敢えてスペースを詰めて1つの文字列になるように書きましたが、/foo x 1 y 2 z 3 でも同じ意味でいいじゃないかと。
で、そういう場合に、
- /foo
- /foo x
- /foo x 1 y
- /foo x 1 /bar
1~3なんかは不正なコマンドラインなわけですが、正規表現でこれらを不正だと見破るのは面倒くさいです。
4 は正当なコマンドラインですが、「/foo x 1」と「/bar」は別のオプションです。が、正規表現だと、「/foo」と「x」と「1 bar」に分けちゃったりするのです。
一番簡単な方法は、/foo:x=1 /foo:y=2 /foo:z=3 という風に書かせて、可変個引数を認めないことですが、それもかっこ悪いなぁ、と。
面倒くさいです。