2010-04-08 91 views
7

我想寫一個類似BNF的形式語法來描述某些GNU/Linux工具的命令行用法。例如,我可以描述cat命令的作爲使用:如何正確地形式化GNU/Linux命令的命令行用法?

(cat-command) : 'cat' (arguments-list) 
(arguments-list) : (argument) 
(arguments-list) : (arguments-list) (argument) 
(argument) : (file) 

問題是我不能寫下一些命令如md5sum精確語法。我在第一次嘗試將是如下:

(md5sum-command) : 'md5sum' (arguments-list) 
(arguments-list) : (argument) 
(arguments-list) : (arguments-list) (argument) 
(argument) : (file) 
(argument) : '--check' 

但正如你所看到的這個語法允許您指定--check參數多次如你所願,這是不正確的,你應該使用它最多一次。

我該如何解決這個問題?另外,爲了更好地對待這類問題,我應該研究什麼樣的正式語法?

+1

你確定你的語法不正確嗎?對我而言,許​​多Unix命令非常高興地接受多次出現的相同的參數,例如'ls -l -l -l'。 – 2010-04-08 12:16:52

+0

是的,你是對的。但也許有一些工具不允許重複。我也可以寫我自己的程序,不允許重複。所以我認爲我的問題仍然相關。 – 2010-04-08 13:55:00

回答

4

你可以嘗試這樣的:

(md5sum-command) : 'md5sum' (arguments-list) 
(arguments-list) : (file-arguments) | '--check' (file-arguments) 
(file-arguments) : (file) (file-arguments) 

假設你希望能夠準確指定每個命令一個--check,但不依賴於它作爲第一個參數,你可以使用:

(md5sum-command) : 'md5sum' (arguments-list) 
(arguments-list) : (file-arguments) | (file-arguments) '--check' (file-arguments) 
(file-arguments) : (file) (file-arguments) 

另請注意,管道(|)符號只是其他規則的快捷方式。以下是等價的:

(md5sum-command) : 'md5sum' (arguments-list) 
(arguments-list) : (file-arguments) 
(arguments-list) : (file-arguments) '--check' (file-arguments) 
(file-arguments) : (file) (file-arguments) 

我會感到驚訝,如果你不能指定大多數UNIX與像那些在BNFs表示上下文無關文法命令。

+0

你的版本似乎有效,但它不夠一般。例如,你不需要在'md5sum'參數後立即加上'--check'參數:你可以在它之前和之後指定許多文件。 – 2010-04-08 13:59:34

+0

在閱讀你的新版本後,我設法寫下了以下內容: (arguments-list):[(files-list)] [(mode-option)] [(files-list)] ['--check'] [(files-list)] (arguments-list):[(files-list)] ['--check'] [(files-list)] [(mode-option)] [(files-list)] (mode-option):'--binary' (mode-option):'--text' 我無法進一步縮寫它。因此,添加諸如「--quiet」,「--warn」或「--status」等其他參數將導致這樣一個簡單命令的語法非常長。 – 2010-04-09 11:43:15

+0

是的。您可能希望在僅有標誌的參數(可以出現在參數列表中的任何位置,全局行爲)和對隨後的文件起作用的參數之間作出區別。 – 2010-04-09 13:00:54

-1

我可能找到了答案,雖然它不是預期的答案。您可以選擇識別命令的正確性,而不是生成正確的命令。使用一些混合語言,你可以寫下面的一組要求:

argument(0) == "md5sum" 
forall i, if i != 0 then argument(i) == "--binary" or 
         argument(i) == "--text" or 
         argument(i) == "--check" or 
         argument(i) == "--status" or 
         argument(i) belongs to <file> 
0 <= instances("--binary") + instances("--text") <= 1 
0 <= instances("--check") <= 1 
if instances("--check") == 1 then 0 <= instances("--status") <= 1 

,因爲我還是想知道是否存在一種方法來產生正確的,我不會紀念這個答案正確的命令。