Prolog 为给定上下文无关语法生成符号字符串(句子)

Prolog 为给定上下文无关语法生成符号字符串(句子),prolog,context-free-grammar,dcg,Prolog,Context Free Grammar,Dcg,我有一个简单的语法,比如 S::=a S b S::=[] (empty string) 现在我想为上述语法编写一个解析器,如 cfg('S', [a,'S',b]) 它通过最左边的派生生成一个句子aaabbb 我没有足够的能力在prolog中处理dcg/cfg。 所以请帮我举个例子,这样我就可以继续尝试更大的东西了。考虑一下这个DCG代码: s-->[]. s-->[a],s,[b]. 要运行DCG定义的谓词,应该在末尾再添加两个参数:“input”和它剩下的内容。如果您想识

我有一个简单的语法,比如

S::=a S b
S::=[] (empty string)
现在我想为上述语法编写一个解析器,如

cfg('S', [a,'S',b])
它通过最左边的派生生成一个句子aaabbb

我没有足够的能力在prolog中处理dcg/cfg。
所以请帮我举个例子,这样我就可以继续尝试更大的东西了。

考虑一下这个DCG代码:

s-->[].
s-->[a],s,[b].
要运行DCG定义的谓词,应该在末尾再添加两个参数:“input”和它剩下的内容。如果您想识别整个列表,只需输入[]。因此,当您运行它时,您会得到:

38 ?- s(C,[]).
C = [] ;
C = [a, b] ;
C = [a, a, b, b] ;
C = [a, a, a, b, b, b] ;
C = [a, a, a, a, b, b, b, b] ;
...
如果需要某种类型的“return”字符串,可以将其添加为额外的arg。要在dcg子句中编写prolog代码,请使用{}:

s('')-->[].
s(S)-->
    [a],s(SI),[b],
    { atomic_list_concat([a,SI,b],S)}.
你会得到:

40 ?- s(R,X,[]).
R = '',
X = [] ;
R = ab,
X = [a, b] ;
R = aabb,
X = [a, a, b, b] ;
R = aaabbb,
X = [a, a, a, b, b, b] ;
R = aaaabbbb,
X = [a, a, a, a, b, b, b, b] ;
R = aaaaabbbbb,
...
我们生成了该语法可以识别的所有字符串;通常,您只需要检查语法是否识别字符串。为此,您只需将其作为输入:

41 ?- s([a,b],[]).
true 

42 ?- s([a,b,b],[]).
false.
请注意,我们将S::=[]规则放在第一位,否则如果您要求生成所有解决方案,prolog将陷入无限循环。用更复杂的语法来解决这个问题可能不是小事。要获得解决方案,可以使用长度/2:

?- length(X,_),s(X,[]).
X = [] ;
X = [a, b] ;
X = [a, a, b, b] ;
X = [a, a, a, b, b, b] ;
X = [a, a, a, a, b, b, b, b] 
即使您的代码是:

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

我对你的解释有点了解。但是坦率地说,如何对生成所有可能字符串的解析器进行编码呢?你能给我完整的密码吗?我真的发现序言非常凝灰岩和混乱??整个代码都是这两行开头。太棒了,不是吗?是的,这是前两行。将它们写在一个文件中并查阅(不能在swi prolog atm中对DCG使用assert/1)非常好!一个细节:最好使用官方的短语/2(或短语/3)接口到DCG,因为其他实现可能会以不同的方式将DCG规则转换为纯Prolog代码。使用短语/2可以使程序在各种实现之间保持可移植性,例如,您可以编写短语(s,Ls),而不是s(Ls),是的,它是一个内置谓词。第一个参数是原子列表,第二个是它们的串联。我认为它是最近在swi prolog中添加的,所以您可能需要将其替换为atom_concat(a,SI,Temp),atom_concat(Temp,b,S)。