如何正确地形式化GNU / Linux命令的命令行用法?

时间:2010-04-08 12:11:27

标签: grammar bnf

我想写一个类似BNF的正式语法来描述某些GNU / Linux工具的命令行用法。例如,我可以将cat命令的用法描述为:

(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参数,这是不正确的,因为您最多应该使用它一次。

我该如何解决?另外,为了更好地处理这类问题,我应该研究什么样的正式语法?

2 个答案:

答案 0 :(得分: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)

如果您无法使用像BNF中表达的那样使用无上下文语法指定大多数unix命令,我会感到惊讶。

答案 1 :(得分:-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

我不会将此答案标记为正确答案,因为我仍然很想知道是否存在生成正确命令的方法。