prolog – 从含糊不清的语法转换为明确的语法

我有一个模糊的无上下文语法,它有产品:

s --> [0],s,[1].
s --> [0],s.
s --> [].

这当然是模棱两可的,因为对于00011我可以画另外两个解析树.我必须编写我的语法,这是一种明确的语法并描述相同的语言.我的想法是:

   s --> [0],s,[1].
   s --> [0],a.
   s --> [].
   a --> [0],a.
   a --> [].

很好?我怎么能证明这一点?

最佳答案 那你怎么能证明模棱两可呢?在Prolog中,具体句子很容易实现:

| ?- length(Xs,N), bagof(t,phrase(s,Xs),[_,_|_]).              

N = 3
Xs = [0,0,1] ? ;

N = 4
Xs = [0,0,0,1] ? ;

N = 5
Xs = [0,0,0,0,1] ? ;

N = 5
Xs = [0,0,0,1,1] ? ;

N = 6
Xs = [0,0,0,0,0,1] ? 

这证明了混凝土长度的模糊性并给出了相关的反例.

然而,有一个警告可能只在一段时间后显示:bagof / 3必须以某种方式存储整套解决方案.因此,如果此设置非常大,bagof / 3可能会溢出.以下查询以获取冗余解决方案为代价避免了此错误:

| ?- length(Xs,N), phrase(s,Xs), bagof(t,phrase(s,Xs),[_,_|_]).

N = 3
Xs = [0,0,1] ? ;

N = 3
Xs = [0,0,1] ? ;

N = 4
Xs = [0,0,0,1] ? ;

N = 4
Xs = [0,0,0,1] ? ;

N = 4
Xs = [0,0,0,1] ? ;

N = 5
Xs = [0,0,0,1,1] ...

通过改进的语法,查询循环.这意味着系统无法找到反例.至少不是长度低于1000这是我测试的.

关于在Prolog中编写DCG的一些一般性评论:

>尝试将递归案例放在最后,这可能会节省一些空间.
>您可能希望使用双引号字符串来表示终端.有关更多信息,请参见this answer

点赞