2010-04-08 58 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 

,因为我还是想知道是否存在一种方法来产生正确的,我不会纪念这个答案正确的命令。