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 Bobfor Rel。我尝试在标签之间使用非空格分隔符,效果很好。我应该如何重写label_with_spaces谓词以仅消耗所需的输入?

4

1 回答 1

1

您的解决方案中的问题是您在时间之前提交解析(使用剪切,!)当您解析 letters_or_spaces 时,您真的不知道要处理多少输入,因为您必须解析到倒数第二个标签(在空格)。

因此,您应该让序言引擎在该谓词中回溯,以允许在 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 回答