计算Prolog中的定语从句语法递归

Counting definite clause grammar recursions in Prolog

我有以下Prolog定句语法:

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

这将导致与[a,b,a,b]之类的词相反地接受[a,a,b,b]之类的词。简而言之,语法显然是a ^ n b ^ n。现在,我想将n返回给用户。如何计算n?


1
2
s(X)-->[a],s(Y),[b],{X is Y+1}.
s(0)-->[].

需要给DCG非端子提供参数。请注意,平等并不完全像命令式编程语言的分配那样工作,因此使用X为Y1。

一些示例输出:

1
2
3
4
5
6
s(X,[a,b,b,b],[]).
false.

s(X,[a,a,a,b,b,b],[]).
X = 3 ;
false.


与地面弦弦配合使用时,@ thequark和@LittleBobbyTables的答案可以很好地发挥作用。

但是,如果它们的长度不受限制,例如以下查询,该怎么办?

1
2
3
4
5
?- phrase(s(3),_).               % expected: success  
%                                  observed: no answer(s)

?- phrase(s(-10),_).             % expected: failure
%                                  observed: no answer(s)

我们当然希望上述查询能够普遍终止!
让我们使用clpfd并写:

1
2
3
4
:- use_module(library(clpfd)).

s(0) --> [].
s(N) --> {N#>0,N#=N0+1},[a],s(N0),[b].

示例查询:

1
2
3
4
5
6
7
8
9
10
?- phrase(s(N),[a,a,a,a,b,b,b,b]).
N = 4 ;                          % works like in the other answers
false.

?- phrase(s(3),Xs).
Xs = [a,a,a,b,b,b] ;             % now, this works too!
false.                           % (terminates universally)

?- phrase(s(-10),_).             % fails, like it should
false.

1
2
3
s(N, M) --> [a], {N1 is N + 1}, s(N1, M), [b].
s(N, N) --> [].
s(N) --> s(0, N).

用法:

1
2
?- phrase(s(N), [a,a,a,b,b,b]).
N = 3