鉴于CFG
S --> a S b | c | d
我想写一个谓词,如语法('S',句子),它会生成所有可能的
sentences like
sentence=acb,
sentence=acd,
sentence=c,
sentence=ab......................
使用最左边的派生,如果遇到的符号是终端,它应打印出该终端,如果遇到的符号是非终端 'S',它应该回溯并替换其中一个语法 a S b或c或d 并重复此过程。
我不想要任何代码......只是帮我提一些如何开始的提示
答案 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)
。