Prolog dcg生成语言中的所有单词

时间:2012-03-25 22:16:28

标签: prolog dcg left-recursion

我正在尝试在prolog中编写一些dcg语法来描述语言 a^nb^n n>=0
"",ab,aabb,aaabbb itd

我写的所有内容都是

s --> slowo.
slowo --> [a],slowo,[b],!.
slowo --> [].  

只要我想要做的只是检查单词是否正确,它的好处是什么,但是如果?-phrase(s,X)能够生成我语言中的所有单词,那么dcg语法应该如何查找prolog?

3 个答案:

答案 0 :(得分:3)

除了@Mog的答案之外,让我们考虑一般情况:

如果语法如此复杂,重新排序DCG规则将无济于事?我们怎样才能列举所有句子?如果语法以这种方式表达,它终止一个固定长度,我们得到所有句子

?- length(Xs, N), phrase(s, Xs).

单独的目标length将以公平的方式列举所有列表。也就是说,从最短的[]开始,枚举所有列表:

?- length(Xs, N).
Xs = [],
N = 0 ;
Xs = [_G307],
N = 1 ;
Xs = [_G307, _G310],
N = 2 ;
Xs = [_G307, _G310, _G313],
N = 3 ;
Xs = [_G307, _G310, _G313, _G316],
N = 4 ; ...

现在,长度固定,目标phrase(s, Xs)将找到该固定长度的所有答案。举个例子,看看Mat对this grammar的回答。

因此,这是检查语法句子的一般方法。但是 - 这种普遍性需要付出代价!对于句子数量有限的语法,out方法不会终止:

:- use_module( library(double_quotes) ).

s --> "a"|"b".

?- phrase(s, Xs).
Xs = "a" ;
Xs = "b".

这个语法开箱即用,但我们现在得到length/2

?- length(Xs, N),phrase(s, Xs).
Xs = "a",
N = 1 ;
Xs = "b",
N = 1 ;
**loops**

此方法通常称为iterative deepening,尽管此术语更精确地强加了派生深度的约束。但我们对实际的“输出”施加了约束力。因此,迭代加深也能够处理左递归,而length/2仅适用于以固定输入长度终止的语法。

这项技术在Prolog中特别有趣的原因在于它与Prolog的时间顺序回溯机制完美融合。

答案 1 :(得分:2)

在SWI Prolog中,我可以使用:

s(X, []).

phrase(s, X).

(正如你的建议)获取所有字符串。但是,为了在没有堆栈溢出的情况下生成任何答案,我需要颠倒slowo的两个规则的顺序,并从递归规则中删除剪切。

答案 2 :(得分:2)

如果您是从Prolog开始,请尽量避免使用!/0。没有它,你通常可以做得更好。

例如,您的语法可以写成如下:

s --> [].
s --> [a], s, [b].

并查询如下:

?- phrase(s, X).

请注意,prolog子句从左到右,从上到下被选中,因此在涉及回溯时,优先考虑写在另一个的顶部的规则。