List 用prolog编写上下文无关语法

List 用prolog编写上下文无关语法,list,prolog,context-free-grammar,dcg,List,Prolog,Context Free Grammar,Dcg,假设我有以下上下文无关语法 S -> A A -> mAn A -> o 这在序言中会是什么样子?这是我试过的,但不起作用。第二行似乎是问题所在 S(Z) :- A(Z). A(Z) :- append([m],X,Z2), A(X), append(Z2,[n],Z). A([o]). 由于语法不是左递归的,我们可以使用: 然后我们可以解析或生成所有接受的序列。例如,生成: ?- length(L, _), phrase(s, L). L = [o] L = [m, o

假设我有以下上下文无关语法

S -> A
A -> mAn
A -> o
这在序言中会是什么样子?这是我试过的,但不起作用。第二行似乎是问题所在

S(Z) :- A(Z).
A(Z) :- append([m],X,Z2), A(X), append(Z2,[n],Z).
A([o]).

由于语法不是左递归的,我们可以使用:

然后我们可以解析或生成所有接受的序列。例如,生成:

?- length(L, _), phrase(s, L).
L = [o] 
L = [m, o, n] 
L = [m, m, o, n, n] 
...
要检查Prolog代码,请执行以下操作:

?- listing(s).
s(A, B) :-
    a(A, B).

?- listing(a).
a([m|A], C) :-
    a(A, B),
    B=[n|C].
a([o|A], A).
由于差异列表,无需追加/3

使用append/3进行编辑

s(Z) :- a(Z).
a(Z) :- append([m|X],[n],Z), a(X).
a([o]).
SWI Prolog有append/2(简单地基于append/3正确链接),它提供 更具可读性的替代方案

a(Z) :- append([[m],X,[n]], Z), a(X).

无论如何,我们必须在构建/拆分列表后递归调用a/1。在这个答案中,我们使用常用的谓词

s(Xs):- a(Xs)。 a([o])。 a([m|Xs]):- (Xs0,[n],Xs), a(Xs0)。 示例查询:

?- length(Xs,_), s(Xs). Xs = [o] ; Xs = [m,o,n] ; Xs = [m,m,o,n,n] ; Xs = [m,m,m,o,n,n,n] ... ?-(Xs,uz),s(Xs)。 Xs=[o] ; Xs=[m,o,n] ; Xs=[m,m,o,n,n] ; Xs=[m,m,m,o,n,n,n] ...
注意:使用
append/3
而不是,通常是一个错误的选择,可能会降低运行时性能和代码可读性。只要可能,请改用

酷。如果使用append/3会是什么样子?为什么将
a([o])。
放在最后?@false:我试图使代码与原始代码保持最相似,而不是写入
a(Z)
,但是
a(Z)
。与所有谓词名称类似。。。 s(Xs) :- a(Xs). a([o]). a([m|Xs]) :- append(Xs0,[n],Xs), a(Xs0). ?- length(Xs,_), s(Xs). Xs = [o] ; Xs = [m,o,n] ; Xs = [m,m,o,n,n] ; Xs = [m,m,m,o,n,n,n] ...