处理prolog上下文无关语法

时间:2011-11-30 19:54:50

标签: prolog context-free-grammar dcg prolog-dif

鉴于CFG

S --> a S b | c | d

我想写一个谓词,如语法('S',句子),它会生成所有可能的

sentences like
sentence=acb,
sentence=acd,
sentence=c,
sentence=ab......................

使用最左边的派生,如果遇到的符号是终端,它应打印出该终端,如果遇到的符号是非终端 'S',它应该回溯并替换其中一个语法 a S b或c或d 并重复此过程。

我不想要任何代码......只是帮我提一些如何开始的提示

1 个答案:

答案 0 :(得分:8)

让我们使用DCG对你的语法进行字面编码!

s --> [a], s, [b] | [c] | [d].

?- phrase(s,Xs).
ERROR: Out of local stack

似乎此查询未终止。即Prolog的非常简单的执行策略没有找到解决方案。另一方面,想一想:你的语法描述了一组无限的句子。如果您枚举无限集,则很容易“错误地”开始。这就是Prolog在这里所做的事情。

但事情并没有那么糟糕。怎么样枚举固定长度的所有句子。我会尝试5:

?- length(Xs,5), phrase(s,Xs).
Xs = "aacbb" ;
Xs = "aadbb" ;
false.

在这种情况下,所有句子都被找到,Prolog甚至向我们保证没有其他句子。

?- length(Xs,4), phrase(s,Xs).
false.

没有长度为4的句子。

我们现在可以枚举所有句子,按长度

?- length(Xs,N), phrase(s,Xs).
Xs = "c",
N = 1 ;
Xs = "d",
N = 1 ;
Xs = "acb",
N = 3 ;
Xs = "adb",
N = 3 ;
Xs = "aacbb",
N = 5 ;
Xs = "aadbb",
N = 5 ;
Xs = "aaacbbb",
N = 7

我们在这里使用了什么样的派生?老实说,我不知道,我也不在乎。重要的是要知道Prolog何时终止。在这种情况下,如果长度已知,它将终止。这就是我们需要知道的所有内容,以确保我们拥有无限集的公平枚举。情况甚至更好:s//0也将在长度未知的情况下终止,如

?- Xs = [a,a,b|_], phrase(s,Xs).
false.

?- Xs = [a,a,c|_], phrase(s,Xs).
Xs = "aacbb" ;
false.

?- dif(X,Y), Xs = [X,Y|_], phrase(s,Xs).
X = a,
Y = c,
Xs = "acb" ;
X = a,
Y = d,
Xs = "adb" ;
false.

编辑:我使用"acb"对列表[a,c,b]获得了关于顶级答案的一些问题:请参阅this answer获取解释并library(double_quotes)