J'essaye d'écrire un DCG pour une interface de commande. L'idée est de lire une chaîne d'entrée, de la diviser en espaces, et de transmettre la liste de jetons qui en résulte à un DCG pour l'analyser en une commande et des arguments. Le résultat de l'analyse devrait être une liste de termes que je peux utiliser avec =..
pour construire un objectif à appeler. Cependant, je suis devenu vraiment confus par la situation du type de chaîne dans SWI-Prolog (voir 7.2.3). SWI-Prolog inclut une bibliothèque de basic DCG functionality, incluant un objectif integer//1
qui est supposé analyser un entier. Il échoue en raison d'une erreur de type, mais le plus gros problème est que je n'arrive pas à comprendre comment faire fonctionner correctement un DCG dans SWI-Prolog avec des "listes de jetons".Erreurs de type Prolog avec fonctions de bibliothèque DCG
Voici ce que je suis en train de faire:
:- use_module(library(dcg/basics)).
% integer//1 is from the dcg/basics lib
amount(X) --> integer(X), { X > 0 }.
cmd([show,all]) --> ["show"],["all"].
cmd([show,false]) --> ["show"].
cmd([skip,X]) --> ["skip"], amount(X).
% now in the interpreter:
?- phrase(cmd(L), ["show","all"]).
L = [show, all].
% what is the problem with this next query?
?- phrase(cmd(L), ["skip", "50"]).
ERROR: code_type/2: Type error: `character' expected, found `"50"' (a string)
J'ai lu Section 5.2 du manuel SWI, mais cela n'a pas tout à fait répondre à mes questions:
- Quel type est attendu par
integer//1
dans la bibliothèquedcg/basics
? Le message d'erreur dit "caractère", mais je ne trouve aucune référence utile quant à ce que cela signifie exactement et comment lui fournir une entrée "correcte". - Comment puis-je transmettre une liste de chaînes (jetons) à
phrase/2
afin que je puisse utiliserinteger//1
pour analyser un jeton comme un entier? - S'il n'y a aucun moyen d'utiliser la primitive
integer//1
pour analyser une chaîne de chiffres en entier, comment dois-je accomplir cela?
je l'ai fait un peu de expermenting avec l'aide des valeurs différentes pour le drapeau double_quote
dans SWI-Prolog, plus différents formats d'entrée, comme l'utilisation d'une liste d'atomes, en utilisant une seule chaîne comme l'entrée, à savoir "skip 50"
plutôt que ["skip", "50"]
, et ainsi de suite, mais j'ai l'impression qu'il existe des hypothèses sur le fonctionnement des DCG que je ne comprends pas.
J'ai étudié ces trois pages et qui ont beaucoup d'exemples, mais pas tout à fait mes questions portent sur (certains liens omis depuis que je n'ai pas assez réputation d'afficher tous):
- Le tutoriel "Utilisation de grammaires à clauses définies dans SWI-Prolog" par Anne Ogborn
- Un tutoriel d'Amzi! Prologue sur l'écriture d'interfaces de commande en tant que DCG.
- Section 7.3 du tutoriel de JR Fisher Prolog
Une troisième question plus large est de savoir comment générer un message d'erreur si un entier est prévu, mais ne peut pas être analysé comme un, quelque chose comme ceci:
% the user types:
> skip 50x
I didn't understand that number.
Une approche consiste à définir la variable X
dans le DCG ci-dessus à une sorte de valeur d'erreur, puis de vérifier cela plus tard (comme dans le but hypothétique skip/1
qui est censé être appelé par la commande), mais peut-être manière plus idiomatique? La plus grande partie de mon expérience dans l'écriture d'analyseurs vient de l'utilisation des bibliothèques Parsec et Attoparsec de Haskell, qui sont assez déclaratives mais qui fonctionnent un peu différemment, en particulier en ce qui concerne la gestion des erreurs.
Comment est 'integer' défini dans votre DCG? – lurker
Cela fait partie d'une bibliothèque livrée avec SWI-Prolog, documentée [ici] (http://www.swi-prolog.org/pldoc/doc/swi/library/dcg/basics.pl). Je vais modifier le post avec cette information. – DCE
Ce prédicat ('entier (X)') nécessite un argument entier, selon la documentation, mais vous essayez d'analyser un atome (''50 '') avec lui (je suppose que votre prologue SWI est configuré pour interpréter' " 50 "' comme l'atome '' 50''). – lurker