我想写一个类似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
参数,这是不正确的,因为您最多应该使用它一次。
我该如何解决?另外,为了更好地处理这类问题,我应该研究什么样的正式语法?
答案 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
我不会将此答案标记为正确答案,因为我仍然很想知道是否存在生成正确命令的方法。