2016-05-22 9 views
0

コマンドインターフェイス用のDCGを作成しようとしています。アイデアは、入力の文字列を読み取り、スペースで分割し、結果のトークンのリストをDCGに渡してコマンドと引数に解析することです。解析の結果は、=..と一緒に使用して呼び出す目標を構成するための用語のリストにする必要があります。しかし、私はSWI-Prolog(バージョン7.2.3)の文字列型の状況に本当に混乱しました。 SWI-Prologには、basic DCG functionalityのライブラリが含まれています。これには、整数を解析すると想定される目標integer//1が含まれています。これはタイプエラーのために失敗しますが、大きな問題は、「トークンのリスト」を使用してSWI-PrologでDCGをうまく動作させる方法を理解できないことです。DCGライブラリ関数のプロローグタイプエラー

は、ここで私がやろうとしているものです:

:- 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) 

私はSWIマニュアルのSection 5.2を読みましたが、それはかなり私の質問に答えていませんでした:

  1. により期待されているどのようなタイプライブラリdcg/basicsinteger//1?エラーメッセージには「文字」と表示されていますが、正確にはどういう意味か、「適切な」入力をどのように提供するのかに関する有用な参考文献は見つかりません。
  2. phrase/2に文字列(トークン)のリストを渡すと、integer//1を使用してトークンを整数として解析できますか?
  3. integer//1プリミティブを使用して数字の文字列を整数に解析する方法がない場合は、これをどのように行う必要がありますか?

Iたなく、すなわち、double_quote SWI-Prologの中のフラグに加え、入力として単一の文字列を使用して、原子のリストを使用するなど異なる入力フォーマット、異なる値を使用して"skip 50"をexpermentingのかなり["skip", "50"]以上などですが、DCGがどのように機能しているのか分かりません。

私は、同様にこれらの3つのページを研究された例をたくさん持っているが、どれも非常に(私はそれらのすべてを掲示するのに十分な評判を持っていないので、いくつかのリンクは省略)私の問題に対処していない:

  1. チュートリアル「SWI-PrologにおけるDefinite Clause Grammarsの使用」Anne Ogborn著
  2. Amziからのチュートリアル!コマンドインタフェースをDCGとして書くことについてのプロローグ。
  3. 第三、より幅広い質問が整数が期待されているが、1つ、このようなものとして解析できない場合はエラーメッセージを生成する方法であるJRフィッシャーのPrologのチュートリアル

のセクション7.3:

% the user types: 
> skip 50x 
I didn't understand that number. 

1つのアプローチは、上のDCGの変数Xを何らかの種類のエラー値に設定し、後でそれを確認することです(コマンドによって呼び出されると想定される仮想のskip/1のような)が、より慣用的な方法?パーサーを書く際の私の経験の大部分は、HaskellのParsecとAttoparsecライブラリの使用に由来します。これらのライブラリは、かなり宣言的ですが、特にエラー処理に関しては多少異なります。

+0

'integer'あなたDCGで定義されている方法は? – lurker

+0

SWI-Prologに同梱されているライブラリの一部です。[here](http://www.swi-prolog.org/pldoc/doc/swi/library/dcg/basics.pl)に記載されています。この情報で投稿を編集します。 – DCE

+0

その述語( 'integer(X)')は、ドキュメンテーションに従って整数引数を必要としますが、アトム( '' 50 '')を解析しようとしています(SWIプロローグが ' 50 "をアトム" 50 "と呼ぶ)。 – lurker

答えて

0

Prologには文字列がありません。二重引用符で囲まれた文字列の伝統的な表現は、コード(整数)のリストです。 efficiency reasonsについては、SWI-Prolog ver。

?- atomic("a string"). 
true. 

とバッククォートリテラルは、以前の文字列によって保持された役割を持っている:新しいアトミックデータ型として> = 7本の導入弦言うこと

?- X=`123`. 
X = [49, 50, 51]. 

言うまでもなく、これはまた、与えられた、some confusionを引き起こしました...

とにかく、DCGは文字コードの(差分)リストでも機能しますが、トランスレータは文字列を端末として受け入れるように拡張されています。あなたのコードは

cmd([show,all]) --> whites,"show",whites,"all",blanks_to_nl. 
cmd([show,false]) --> whites,"show",blanks_to_nl. 
cmd([skip,X]) --> whites,"skip",whites,amount(X),blanks_to_nl. 

?- phrase(cmd(C), ` skip 2300 `). 
C = [skip, 2300]. 

編集整数が

I期待されている場合はエラーメッセージを生成する方法

のように呼び出すことができるかもしれません試してみる:

... 
cmd([skip,X]) --> whites,"skip",whites,amount(X). 

% integer//1 is from the dcg/basics lib 
amount(X) --> integer(X), { X > 0 }, blanks_to_nl, !. 
amount(unknown) --> string(S), eos, {print_message(error, invalid_int_arg(S))}. 

prolog:message(invalid_int_arg(_)) --> ['I didn\'t understand that number.']. 

テスト:

?- phrase(cmd(C), ` skip 2300x `). 
ERROR: I didn't understand that number. 
C = [skip, unknown] ; 
false. 
+0

したがって、空白は 'phrase/2'への入力に含まれなければなりませんか?私は、トークンのリストを直接処理する方法があることを望んでいました。問題の一部のように、 '整数// 1 'は文字コードのリスト(" 123 "など)を期待していますが、二重引用符で囲まれた文字コードが文字コードのリストを生成していると仮定すると、" 123 " SWI-Prolog 7のフラグとして使用可能)。あれは正しいですか? – DCE

+0

はい、整数// 1は文字コードのリストを予期します(または生成します)。実際、プレーンDCGの場合、トークンは単なる文字コードです。文字列を数値に変換するには、 '? - number_string(X、" 123 ")を使うことができます。たぶん私が紛失している点は、あなたのトークンがどこに来て、なぜ文字列であるのか? – CapelliC

+0

アイデアは、あるストリームから入力行を読み、それをトークンに分解して(例えば、 "do this" - > ["do"、 "this"])、これをDCGに渡して、用語のリストを解析します。これは[ここ](http://www.amzi.com/manuals/amzi/pro/ref_dcg.htm#DCGCommandLanguage)と[ここ](http://www.cpp.edu)に記載されているように、DCGとは自然なことです。 /~jrfisher/www/prolog_tutorial/7_3.html)。前の例はAmziのプロローグですが、私がやりたいことはかなり正確ですが、possibleなら手助けするためにSWI-PrologのDCGプリミティブ(整数// 1など)を使いたいです。タイプがうまくいかないようです私はどのように修正するか分からない。 – DCE