2010-04-08 13 views
7

Je voudrais écrire une grammaire formelle de type BNF pour décrire l'utilisation en ligne de commande de certains outils GNU/Linux. Par exemple, je peux décrire l'utilisation de la commande cat comme:Comment formaliser correctement l'utilisation de la ligne de commande des commandes GNU/Linux?

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

Le problème est que je ne peux pas écrire une grammaire précise pour certaines commandes telles que md5sum. Ma première tentative qui serait la suivante:

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

Mais comme vous pouvez le voir cette grammaire vous permet de spécifier l'argument --check autant de fois que vous le souhaitez, ce qui est incorrect que vous devez l'utiliser au plus une fois .

Comment puis-je résoudre ce problème? Aussi, quel genre de grammaires formelles je devrais étudier pour mieux traiter ce genre de problèmes?

+1

Etes-vous sûr que votre grammaire est incorrecte? Pour moi, beaucoup de commandes Unix acceptent des occurrences multiples du même argument, par exemple 'ls -l -l -l'. –

+0

Oui, vous avez raison. Mais peut-être y a-t-il des outils qui ne permettent pas les répétitions. Je peux aussi écrire mon propre programme qui ne permet pas les répétitions. Donc, je pense que mon problème est toujours pertinent. –

Répondre

4

Vous pouvez essayer quelque chose comme:

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

En supposant que vous voulez être en mesure de préciser exactement une --check par commande, mais pas dépendre le premier argument, vous pouvez utiliser:

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

Notez également que le symbole de tuyau (|) est juste un raccourci pour une règle supplémentaire. Ce qui suit est équivalent:

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

Je serais surpris si vous ne pouviez pas spécifier la plupart des commandes unix avec un contexte grammaire libre comme ceux qui sont exprimés INB.

+0

Votre version semble fonctionner, mais ce n'est pas assez général. Par exemple, vous n'êtes pas obligé de mettre l'argument '--check' immédiatement après l'argument 'md5sum': vous pouvez avoir plusieurs fichiers spécifiés avant et après. –

+0

Après avoir lu votre nouvelle version, j'ai réussi à écrire ce qui suit: (arguments-liste): [(liste de fichiers)] [(option-mode)] [(liste de fichiers)] ['--check'] [(files-list)] (liste-arguments): [(liste-fichiers)] ['--check'] [(liste-fichiers)] [(option-mode)] [(liste-fichiers)] (mode-option): '--binary' (mode-option): '--text' Je ne pouvais pas l'abréger davantage. Donc, ajouter d'autres arguments tels que '--quiet', '--warn' ou '--status' donnerait une grammaire excessivement longue pour une commande aussi simple. –

+0

True. Vous voulez probablement faire une différence entre les arguments qui ne sont que des drapeaux (peuvent apparaître n'importe où dans la liste des arguments, agir globalement) et les arguments qui agissent sur les fichiers suivants. –

-1

J'ai probablement trouvé une réponse, bien que ce ne soit pas celle attendue. Vous pouvez choisir de reconnaître l'exactitude d'une commande au lieu de générer des commandes correctes. En utilisant un langage hybride, vous pouvez écrire l'ensemble des exigences suivantes:

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 

Je ne vais pas marquer cette réponse comme correcte parce que je suis toujours curieux de savoir s'il existe un moyen de générer correcte commandes.