在prolog中编写上下文无关语法

snc*_*pst 5 list prolog context-free-grammar dcg

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

S -> A
A -> mAn
A -> o
Run Code Online (Sandbox Code Playgroud)

这怎么看prolog?这是我尝试过但它不起作用.第二行似乎是问题所在.

S(Z) :- A(Z).
A(Z) :- append([m],X,Z2), A(X), append(Z2,[n],Z).
A([o]).
Run Code Online (Sandbox Code Playgroud)

Cap*_*liC 4

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

s --> a.
a --> [m], a, [n].
a --> [o].
Run Code Online (Sandbox Code Playgroud)

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

?- length(L, _), phrase(s, L).
L = [o] 
L = [m, o, n] 
L = [m, m, o, n, n] 
...
Run Code Online (Sandbox Code Playgroud)

检查 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).
Run Code Online (Sandbox Code Playgroud)

由于有差异列表,不需要append/3

使用append/3进行编辑

s(Z) :- a(Z).
a(Z) :- append([m|X],[n],Z), a(X).
a([o]).
Run Code Online (Sandbox Code Playgroud)

SWI-Prolog 有append/2(简单地基于正确链接的append/3),它提供了一个更具可读性的替代方案

a(Z) :- append([[m],X,[n]], Z), a(X).
Run Code Online (Sandbox Code Playgroud)

无论如何,我们必须在列表构建/拆分递归调用 a/1