1

アルファベットラベル、スペース、スペースまたは文字を含む可能性のある疑似ラベル、別のスペース、別のアルファベットラベル、そして最後にピリオドを受け入れるDCG述語を次のように記述したいと思います。

label_madness --> label(Table1), " ", label_with_spaces(Rel), " ", label(Table2), ".".

ラベルのコードは次のとおりです。

label(A) --> letters(S), {string_to_atom(S, A)}, !.
label_with_spaces(A) --> letters_or_spaces(S), {string_to_atom(S, A)}, !.

letters([C|D]) --> letter(C), letters(D), !.
letters([C]) --> letter(C), !.

letters_or_spaces([C|D]) --> letter(C), letters_or_spaces(D), !.
letters_or_spaces([C|D]) --> spacehyphen(C), letters_or_spaces(D), !.
letters_or_spaces([C]) --> letter(C), !.
letters_or_spaces([C]) --> spacehyphen(C), !.

letter(C) --> [C], {"a"=<C, C=<"z"}, !.
letter(C) --> [C], {"A"=<C, C=<"Z"}, !.
spacehyphen(E) --> " ", {from_list("-", E)}, !. % spaces are replaced with hyphens in the pseudolabel
from_list([E], E).

label_madnessのような文字列をフィードする"Alice is responsible for Bob."と、失敗します。不思議な理由traceで動作を拒否しますが、DCGが全体に一致するため失敗すると思いis responsible for BobますRel。ラベルの間にスペース以外の区切り文字を試してみましたが、正常に機能します。label_with_spaces必要なだけの入力のみを消費するように述語を書き直すにはどうすればよいですか?

4

1 に答える 1

1

ソリューションの問題は、時間の前に解析をコミットしていることです(カットを使用して!)letters_or_spacesを解析する場合、最後から2番目のラベル(内)まで解析する必要があるため、処理する入力の量が実際にはわかりません。スペース)。

したがって、letters_or_spacesで正しいフレーズを選択できるように、その述語でプロローグエンジンをバックトラックさせる必要があります。次のようなもの(コードへの変更を表示するだけで、いくつかの述語句からカットを削除します):

label(A) --> letters(S), {string_to_atom(S, A)}.
label_with_spaces(A) --> letters_or_spaces(S), {string_to_atom(S, A)}.
letters_or_spaces([C|D]) --> letter(C), letters_or_spaces(D).
letters_or_spaces([C|D]) --> spacehyphen(C), letters_or_spaces(D).
letters_or_spaces([C]) --> letter(C).
letters_or_spaces([C]) --> spacehyphen(C).

パーサーを少し変更して、バックトラッキングを使用する代わりに、letters_or_spacesのピリオドまで解析してから、最後のラベルを分割することもできます。

于 2011-02-14T15:05:01.173 に答える