Я хотел бы записать подобную 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
аргумент так много раз, как Вы желаете, который является неправильным, поскольку необходимо использовать его самое большее одно время.
Как я могу зафиксировать это? Кроме того, какие формальные грамматики я должен изучить для лучшей обработки этого вида проблем?
Вы можете попробовать что-нибудь вроде:
(md5sum-command) : 'md5sum' (arguments-list)
(arguments-list) : (file-arguments) | '--check' (file-arguments)
(file-arguments) : (file) (file-arguments)
Предполагая, что вы хотите указать только один - проверьте
для каждой команды, но не в зависимости от того, является ли он первым аргументом, вы можете использовать:
(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 с помощью контекстно-свободной грамматики, подобной выраженной в BNF.
Я, вероятно, нашел ответ, хотя он и не является ожидаемым. Вы можете выбрать распознавание правильности команды вместо генерации правильных команд. Используя какой-нибудь гибридный язык, можно написать следующий набор требований:
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
Я не отмечу этот ответ как правильный, потому что мне все еще интересно узнать, существует ли способ генерировать правильные команды.