自定义 DCG 运算符

Custom DCG Operators

假设我想编写一个自定义运算符来以重复的方式编写 DCG 规则。

例如,假设我有一个 DCG,ws 这样:

ws --> [].
ws --> " ", ws.

匹配零个或多个空格。显然,如果我想在我的语法中的每个标记之间使用可选的空格,那么必须在任何地方都放置 , ws 是令人讨厌的。

我可以定义一个新的运算符来替换 ,/2

:- op(1000, xfy, [ -- ]).
:- meta_predicate --(*,*,?,?).
--(L,R) --> ({callable(L)} -> call(L); L), ws, ({callable(R)} -> call(R); R).

这通过可选的空白规则连接了 --/2 的左右手。这大部分工作正常,但某些事情会出错:

rule --> "foo" -- ("bar"; "quux").

如果我尝试执行此规则,我会收到一条错误消息,指出 ;/4 未定义。我对这里的问题有一个模糊的想法,但基本上问题是:有没有一种方法可以为 DCG 定义新的运算符,使其具有与 ,/2 相同的通用性?

是的,这是可以的

目前主要问题是:

?- callable("foo").
true.

所以,我建议这个更简单的定义:

--(L, R) --> L, ws, R.

另外,我建议:

:- set_prolog_flag(double_quotes, chars).

示例查询:

?- phrase(rule, Ls).
Ls = [f, o, o, b, a, r] ;
Ls = [f, o, o, q, u, u, x] ;
Ls = [f, o, o, ' ', b, a, r] ;
Ls = [f, o, o, ' ', q, u, u, x] ;
Ls = [f, o, o, ' ', ' ', b, a, r] .

再举一个例子,让我们改用这个规则:

rule --> "foo" -- ("bar" | "quux") -- "test".

现在我们得到例如:

?- length(Ls, _), phrase(rule, Ls).
Ls = [f, o, o, b, a, r, t, e, s, t] ;
Ls = [f, o, o, b, a, r, ' ', t, e, s, t] ;
Ls = [f, o, o, q, u, u, x, t, e, s, t] ;
Ls = [f, o, o, ' ', b, a, r, t, e, s, t] ;
Ls = [f, o, o, b, a, r, ' ', ' ', t, e, s, t] ;
Ls = [f, o, o, q, u, u, x, ' ', t, e, s, t] ;
Ls = [f, o, o, ' ', b, a, r, ' ', t, e, s, t] ;
Ls = [f, o, o, ' ', q, u, u, x, t, e, s, t] ;
Ls = [f, o, o, ' ', ' ', b, a, r, t, e, s, t] ;
Ls = [f, o, o, b, a, r, ' ', ' ', ' ', t, e, s, t] .

注意迭代深化如何用于公平枚举。