5

假设我想编写一个自定义运算符来以一种重复的方式组成 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?

4

1 回答 1

7

的,这是可能的。

目前,主要问题是:

?- 可调用(“foo”)。
真的。

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

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

另外,我建议:

:- set_prolog_flag(double_quotes, chars)。

示例查询:

?- 短语(规则,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] 。

作为另一个例子,让我们改用这个规则:

规则 --> "foo" -- ("bar" | "quux") -- "test"。

现在我们得到例如:

?- 长度(Ls,_),短语(规则,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] 。

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

于 2018-07-27T17:43:54.983 回答