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

whd*_*whd 1 prolog left-recursion dcg

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

我写的都是

s --> slowo.
slowo --> [a],slowo,[b],!.
slowo --> [].  
Run Code Online (Sandbox Code Playgroud)

只要我想做的只是检查单词是否正确,它就很好,但是 dcg 语法应该如何在 prolog 中查找,以便?-phrase(s,X)从我的语言中生成所有单词?

fal*_*lse 5

除了@Mog 的回答,让我们考虑更一般的情况:

什么,如果语法如此复杂,重新排序 DCG 规则将无济于事?我们如何仍然枚举所有句子?如果语法以这样的方式表述,即它以固定长度终止,我们得到所有句子

?-长度(Xs,N),短语(s,Xs)。

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 对这个语法的回答。

所以这是检查语法句子的通用方法。但是 - 这种普遍性是要付出代价的!对于句子数有限的文法,out 方法不会终止:

:- use_module(library(double_quotes)).

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

?-短语(s, Xs)。
Xs = "a" ;
Xs = "b"。

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

?-长度(Xs,N),短语(s,Xs)。
Xs = "a",
N = 1 ;
Xs = "b",
N = 1 ;
**循环**

这种方法通常被称为迭代深化,尽管这个术语更准确地强加了推导深度的界限。但是我们对实际的“输出”施加了限制。因此迭代深化也能够处理左递归,而length/2 仅适用于以固定输入长度终止的文法。

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